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
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+ #Author: Roy L Zuo (roylzuo at gmail dot com)
4
+ #Description:
5
+
6
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
7
+
8
+ require ENV['SEQUEL_DB2_SPEC_REQUIRE'] if ENV['SEQUEL_DB2_SPEC_REQUIRE']
9
+
10
+ unless defined?(DB2_DB)
11
+ DB2_DB = Sequel.connect(ENV['SEQUEL_DB2_SPEC_DB']||DB2_URL)
12
+ end
13
+
14
+ if DB2_DB.table_exists?(:test)
15
+ DB2_DB.drop_table :test
16
+ end
17
+ INTEGRATION_DB = DB2_DB unless defined?(INTEGRATION_DB)
18
+
19
+ describe Sequel::Database do
20
+ before do
21
+ @db = DB2_DB
22
+ @db.create_table(:test){String :a}
23
+ @ds = @db[:test]
24
+ end
25
+
26
+ after do
27
+ @db.drop_table(:test)
28
+ end
29
+
30
+ specify "should provide disconnect functionality after preparing a connection" do
31
+ @ds.prepare(:first, :a).call
32
+ @db.disconnect
33
+ @db.pool.size.should == 0
34
+ end
35
+
36
+ specify "should return version correctly" do
37
+ @db.db2_version.should match(/DB2 v/i)
38
+ end
39
+ end
40
+
41
+ describe "Simple Dataset operations" do
42
+ before do
43
+ DB2_DB.create_table!(:items) do
44
+ Integer :id, :primary_key => true
45
+ Integer :number
46
+ end
47
+ @ds = DB2_DB[:items]
48
+ @ds.insert(:number=>10, :id => 1 )
49
+ end
50
+ after do
51
+ DB2_DB.drop_table(:items)
52
+ end
53
+ cspecify "should insert with a primary key specified", :mssql do
54
+ @ds.insert(:id=>100, :number=>20)
55
+ @ds.count.should == 2
56
+ @ds.order(:id).all.should == [{:id=>1, :number=>10}, {:id=>100, :number=>20}]
57
+ end
58
+ end
59
+
60
+ describe Sequel::Database do
61
+ before do
62
+ @db = DB2_DB
63
+ end
64
+ after do
65
+ @db.drop_table(:items)
66
+ end
67
+ specify "should parse primary keys from the schema properly" do
68
+ @db.create_table!(:items){Integer :number}
69
+ @db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == []
70
+ @db.create_table!(:items){primary_key :number}
71
+ @db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number]
72
+ @db.create_table!(:items){Integer :number1, :null => false; Integer :number2, :null => false; primary_key [:number1, :number2]}
73
+ @db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.should == [:number1, :number2]
74
+ end
75
+ end
76
+
77
+ describe "Sequel::IBMDB.convert_smallint_to_bool" do
78
+ before do
79
+ @db = DB2_DB
80
+ @db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
81
+ @ds = @db[:booltest]
82
+ end
83
+ after do
84
+ Sequel::IBMDB.convert_smallint_to_bool = true
85
+ @db.drop_table(:booltest)
86
+ end
87
+
88
+ specify "should consider smallint datatypes as boolean if set, but not larger smallints" do
89
+ @db.schema(:booltest, :reload=>true).first.last[:type].should == :boolean
90
+ @db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
91
+ Sequel::IBMDB.convert_smallint_to_bool = false
92
+ @db.schema(:booltest, :reload=>true).first.last[:type].should == :integer
93
+ @db.schema(:booltest, :reload=>true).first.last[:db_type].should match /smallint/i
94
+ end
95
+
96
+ specify "should return smallints as bools and integers as integers when set" do
97
+ Sequel::IBMDB.convert_smallint_to_bool = true
98
+ @ds.delete
99
+ @ds << {:b=>true, :i=>10}
100
+ @ds.all.should == [{:b=>true, :i=>10}]
101
+ @ds.delete
102
+ @ds << {:b=>false, :i=>0}
103
+ @ds.all.should == [{:b=>false, :i=>0}]
104
+ @ds.delete
105
+ @ds << {:b=>true, :i=>1}
106
+ @ds.all.should == [{:b=>true, :i=>1}]
107
+ end
108
+
109
+ specify "should return all smallints as integers when unset" do
110
+ Sequel::IBMDB.convert_smallint_to_bool = false
111
+ @ds.delete
112
+ @ds << {:b=>true, :i=>10}
113
+ @ds.all.should == [{:b=>1, :i=>10}]
114
+ @ds.delete
115
+ @ds << {:b=>false, :i=>0}
116
+ @ds.all.should == [{:b=>0, :i=>0}]
117
+
118
+ @ds.delete
119
+ @ds << {:b=>1, :i=>10}
120
+ @ds.all.should == [{:b=>1, :i=>10}]
121
+ @ds.delete
122
+ @ds << {:b=>0, :i=>0}
123
+ @ds.all.should == [{:b=>0, :i=>0}]
124
+ end
125
+ end if DB2_DB.adapter_scheme == :ibmdb
126
+
127
+ describe "Simple Dataset operations in transactions" do
128
+ before do
129
+ DB2_DB.create_table!(:items_insert_in_transaction) do
130
+ Integer :id, :primary_key => true
131
+ integer :number
132
+ end
133
+ @ds = DB2_DB[:items_insert_in_transaction]
134
+ end
135
+ after do
136
+ DB2_DB.drop_table(:items_insert_in_transaction)
137
+ end
138
+
139
+ specify "should insert correctly with a primary key specified inside a transaction" do
140
+ DB2_DB.transaction do
141
+ @ds.insert(:id=>100, :number=>20)
142
+ @ds.count.should == 1
143
+ @ds.order(:id).all.should == [{:id=>100, :number=>20}]
144
+ end
145
+ end
146
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
3
 
3
4
  require ENV['SEQUEL_MSSQL_SPEC_REQUIRE'] if ENV['SEQUEL_MSSQL_SPEC_REQUIRE']
@@ -440,3 +441,38 @@ describe "MSSQL::Dataset#count" do
440
441
  MSSQL_DB[:items].select(:name, :value).group(:name, :value).order(:name).count.should == 1
441
442
  end
442
443
  end
444
+
445
+ describe "MSSQL::Database#create_table" do
446
+ specify "should support collate with various other column options" do
447
+ MSSQL_DB.create_table!(:items){ String :name, :size => 128, :collate => :sql_latin1_general_cp1_ci_as, :default => 'foo', :null => false, :unique => true}
448
+ MSSQL_DB[:items].insert
449
+ MSSQL_DB[:items].select_map(:name).should == ["foo"]
450
+ end
451
+ end
452
+
453
+ describe "MSSQL::Database#mssql_unicode_strings = false" do
454
+ before do
455
+ MSSQL_DB.mssql_unicode_strings = false
456
+ end
457
+ after do
458
+ MSSQL_DB.drop_table(:items)
459
+ MSSQL_DB.mssql_unicode_strings = true
460
+ end
461
+
462
+ specify "should work correctly" do
463
+ MSSQL_DB.create_table!(:items){String :name}
464
+ MSSQL_DB[:items].mssql_unicode_strings.should == false
465
+ MSSQL_DB[:items].insert(:name=>'foo')
466
+ MSSQL_DB[:items].select_map(:name).should == ['foo']
467
+ end
468
+
469
+ specify "should be overridable at the dataset level" do
470
+ MSSQL_DB.create_table!(:items){String :name}
471
+ ds = MSSQL_DB[:items]
472
+ ds.mssql_unicode_strings.should == false
473
+ ds.mssql_unicode_strings = true
474
+ ds.mssql_unicode_strings.should == true
475
+ ds.insert(:name=>'foo')
476
+ ds.select_map(:name).should == ['foo']
477
+ end
478
+ end
@@ -82,6 +82,12 @@ describe "MySQL", '#create_table' do
82
82
  end
83
83
  @db.schema(:dolls).map{|k, v| v[:auto_increment]}.should == [nil, nil, true]
84
84
  end
85
+
86
+ specify "should support collate with various other column options" do
87
+ @db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
88
+ @db[:dolls].insert
89
+ @db[:dolls].select_map(:name).should == ["foo"]
90
+ end
85
91
  end
86
92
 
87
93
  describe "A MySQL database" do
@@ -950,7 +956,7 @@ describe "MySQL::Dataset#calc_found_rows" do
950
956
  end
951
957
  end
952
958
 
953
- if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
959
+ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc or MYSQL_DB.adapter_scheme == :mysql2
954
960
  describe "MySQL Stored Procedures" do
955
961
  before do
956
962
  MYSQL_DB.create_table(:items){Integer :id; Integer :value}
@@ -971,26 +977,37 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
971
977
  MYSQL_DB[:items].count.should == 0
972
978
  end
973
979
 
974
- specify "should be callable on the dataset object" do
975
- MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
976
- MYSQL_DB[:items].delete
977
- @d = MYSQL_DB[:items]
978
- @d.call_sproc(:select, :test_sproc, 3).should == []
979
- @d.insert(:value=>1)
980
- @d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
981
- @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
982
- @d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
980
+ # Mysql2 doesn't support stored procedures that return result sets, probably because
981
+ # CLIENT_MULTI_RESULTS is not set.
982
+ unless MYSQL_DB.adapter_scheme == :mysql2
983
+ specify "should be callable on the dataset object" do
984
+ MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
985
+ MYSQL_DB[:items].delete
986
+ @d = MYSQL_DB[:items]
987
+ @d.call_sproc(:select, :test_sproc, 3).should == []
988
+ @d.insert(:value=>1)
989
+ @d.call_sproc(:select, :test_sproc, 4).should == [{:id=>nil, :value=>1, :b=>4}]
990
+ @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
991
+ @d.call_sproc(:select, :test_sproc, 3).should == [{:id=>nil, :value=>2, :b=>6}]
992
+ end
993
+
994
+ specify "should be callable on the dataset object with multiple arguments" do
995
+ MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER, c INTEGER) BEGIN SELECT *, a AS b, c AS d FROM items; END')
996
+ MYSQL_DB[:items].delete
997
+ @d = MYSQL_DB[:items]
998
+ @d.call_sproc(:select, :test_sproc, 3, 4).should == []
999
+ @d.insert(:value=>1)
1000
+ @d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
1001
+ @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
1002
+ @d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
1003
+ end
983
1004
  end
984
-
985
- specify "should be callable on the dataset object with multiple arguments" do
986
- MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER, c INTEGER) BEGIN SELECT *, a AS b, c AS d FROM items; END')
1005
+
1006
+ specify "should deal with nil values" do
1007
+ MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(i INTEGER, v INTEGER) BEGIN INSERT INTO items VALUES (i, v); END')
987
1008
  MYSQL_DB[:items].delete
988
- @d = MYSQL_DB[:items]
989
- @d.call_sproc(:select, :test_sproc, 3, 4).should == []
990
- @d.insert(:value=>1)
991
- @d.call_sproc(:select, :test_sproc, 4, 5).should == [{:id=>nil, :value=>1, :b=>4, :d=>5}]
992
- @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
993
- @d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
1009
+ MYSQL_DB.call_sproc(:test_sproc, :args=>[1, nil])
1010
+ MYSQL_DB[:items].all.should == [{:id=>1, :value=>nil}]
994
1011
  end
995
1012
  end
996
1013
  end
@@ -514,11 +514,6 @@ describe "Postgres::Dataset#insert" do
514
514
  @db.sqls.last.should == 'INSERT INTO test5 (value) VALUES (10) RETURNING xid'
515
515
  end
516
516
 
517
- specify "should have insert_returning_sql use the RETURNING keyword" do
518
- @ds.insert_returning_sql(:xid, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING xid"
519
- @ds.insert_returning_sql('*'.lit, :value=>10).should == "INSERT INTO test5 (value) VALUES (10) RETURNING *"
520
- end
521
-
522
517
  specify "should have insert_select return nil if server_version < 80200" do
523
518
  @ds.meta_def(:server_version){80100}
524
519
  @ds.insert_select(:value=>10).should == nil
@@ -606,12 +601,6 @@ describe "Postgres::Database schema qualified tables" do
606
601
  POSTGRES_DB.drop_table(:domains)
607
602
  end
608
603
 
609
- specify "#table_exists? should not include tables from the default non-public schemas" do
610
- POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
611
- POSTGRES_DB.table_exists?(:schema_test).should == true
612
- POSTGRES_DB.table_exists?(:domain_udt_usage).should == false
613
- end
614
-
615
604
  specify "#table_exists? should see if the table is in a given schema" do
616
605
  POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
617
606
  POSTGRES_DB.table_exists?(:schema_test__schema_test).should == true
@@ -909,7 +898,7 @@ describe "Postgres::Database functions, languages, and triggers" do
909
898
  after do
910
899
  @d.drop_function('tf', :if_exists=>true, :cascade=>true)
911
900
  @d.drop_function('tf', :if_exists=>true, :cascade=>true, :args=>%w'integer integer')
912
- @d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
901
+ @d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
913
902
  @d.drop_table(:test) rescue nil
914
903
  end
915
904
 
@@ -940,19 +929,19 @@ describe "Postgres::Database functions, languages, and triggers" do
940
929
 
941
930
  specify "#create_language and #drop_language should create and drop languages" do
942
931
  @d.send(:create_language_sql, :plpgsql).should == 'CREATE LANGUAGE plpgsql'
943
- @d.create_language(:plpgsql, :replace=>true)
932
+ @d.create_language(:plpgsql, :replace=>true) if @d.server_version < 90000
944
933
  proc{@d.create_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
945
934
  @d.send(:drop_language_sql, :plpgsql).should == 'DROP LANGUAGE plpgsql'
946
- @d.drop_language(:plpgsql)
947
- proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError)
935
+ @d.drop_language(:plpgsql) if @d.server_version < 90000
936
+ proc{@d.drop_language(:plpgsql)}.should raise_error(Sequel::DatabaseError) if @d.server_version < 90000
948
937
  @d.send(:create_language_sql, :plpgsql, :replace=>true, :trusted=>true, :handler=>:a, :validator=>:b).should == (@d.server_version >= 90000 ? 'CREATE OR REPLACE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b' : 'CREATE TRUSTED LANGUAGE plpgsql HANDLER a VALIDATOR b')
949
938
  @d.send(:drop_language_sql, :plpgsql, :if_exists=>true, :cascade=>true).should == 'DROP LANGUAGE IF EXISTS plpgsql CASCADE'
950
939
  # Make sure if exists works
951
- @d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true)
940
+ @d.drop_language(:plpgsql, :if_exists=>true, :cascade=>true) if @d.server_version < 90000
952
941
  end
953
942
 
954
943
  specify "#create_trigger and #drop_trigger should create and drop triggers" do
955
- @d.create_language(:plpgsql)
944
+ @d.create_language(:plpgsql) if @d.server_version < 90000
956
945
  @d.create_function(:tf, 'BEGIN IF NEW.value IS NULL THEN RAISE EXCEPTION \'Blah\'; END IF; RETURN NEW; END;', :language=>:plpgsql, :returns=>:trigger)
957
946
  @d.send(:create_trigger_sql, :test, :identity, :tf, :each_row=>true).should == 'CREATE TRIGGER identity BEFORE INSERT OR UPDATE OR DELETE ON test FOR EACH ROW EXECUTE PROCEDURE tf()'
958
947
  @d.create_table(:test){String :name; Integer :value}
@@ -973,17 +962,17 @@ describe "Postgres::Database functions, languages, and triggers" do
973
962
  end
974
963
 
975
964
  if POSTGRES_DB.adapter_scheme == :postgres
976
- describe "Postgres::Dataset #use_cursor" do
977
- before(:all) do
978
- @db = POSTGRES_DB
979
- @db.create_table!(:test_cursor){Integer :x}
980
- @db.sqls.clear
981
- @ds = @db[:test_cursor]
982
- @db.transaction{1001.times{|i| @ds.insert(i)}}
983
- end
984
- after(:all) do
985
- @db.drop_table(:test) rescue nil
986
- end
965
+ describe "Postgres::Dataset #use_cursor" do
966
+ before(:all) do
967
+ @db = POSTGRES_DB
968
+ @db.create_table!(:test_cursor){Integer :x}
969
+ @db.sqls.clear
970
+ @ds = @db[:test_cursor]
971
+ @db.transaction{1001.times{|i| @ds.insert(i)}}
972
+ end
973
+ after(:all) do
974
+ @db.drop_table(:test_cursor) rescue nil
975
+ end
987
976
 
988
977
  specify "should return the same results as the non-cursor use" do
989
978
  @ds.all.should == @ds.use_cursor.all
@@ -1005,5 +994,103 @@ describe "Postgres::Dataset #use_cursor" do
1005
994
  @ds.check_return
1006
995
  @ds.all.should == @ds.use_cursor.all
1007
996
  end
997
+ end
998
+
999
+ describe "Postgres::PG_NAMED_TYPES" do
1000
+ before do
1001
+ @db = POSTGRES_DB
1002
+ Sequel::Postgres::PG_NAMED_TYPES[:interval] = lambda{|v| v.reverse}
1003
+ @db.instance_eval do
1004
+ disconnect
1005
+ @conversion_procs = nil
1006
+ end
1007
+ end
1008
+ after do
1009
+ Sequel::Postgres::PG_NAMED_TYPES.delete(:interval)
1010
+ @db.instance_eval do
1011
+ disconnect
1012
+ @conversion_procs = nil
1013
+ end
1014
+ @db.drop_table(:foo)
1015
+ end
1016
+
1017
+ specify "should look up conversion procs by name" do
1018
+ @db.create_table!(:foo){interval :bar}
1019
+ @db[:foo].insert('21 days')
1020
+ @db[:foo].get(:bar).should == 'syad 12'
1021
+ end
1022
+ end
1008
1023
  end
1024
+
1025
+ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRES_DB.server_version >= 90000
1026
+ describe "Postgres::Database#copy_table" do
1027
+ before(:all) do
1028
+ @db = POSTGRES_DB
1029
+ @db.create_table!(:test_copy){Integer :x; Integer :y}
1030
+ ds = @db[:test_copy]
1031
+ ds.insert(1, 2)
1032
+ ds.insert(3, 4)
1033
+ end
1034
+ after(:all) do
1035
+ @db.drop_table(:test_copy) rescue nil
1036
+ end
1037
+
1038
+ specify "without a block or options should return a text version of the table as a single string" do
1039
+ @db.copy_table(:test_copy).should == "1\t2\n3\t4\n"
1040
+ end
1041
+
1042
+ specify "without a block and with :format=>:csv should return a csv version of the table as a single string" do
1043
+ @db.copy_table(:test_copy, :format=>:csv).should == "1,2\n3,4\n"
1044
+ end
1045
+
1046
+ specify "should treat string as SQL code" do
1047
+ @db.copy_table('COPY "test_copy" TO STDOUT').should == "1\t2\n3\t4\n"
1048
+ end
1049
+
1050
+ specify "should respect given :options options" do
1051
+ @db.copy_table(:test_copy, :options=>"FORMAT csv, HEADER TRUE").should == "x,y\n1,2\n3,4\n"
1052
+ end
1053
+
1054
+ specify "should respect given :options options when :format is used" do
1055
+ @db.copy_table(:test_copy, :format=>:csv, :options=>"QUOTE '''', FORCE_QUOTE *").should == "'1','2'\n'3','4'\n"
1056
+ end
1057
+
1058
+ specify "should accept dataset as first argument" do
1059
+ @db.copy_table(@db[:test_copy].cross_join(:test_copy___tc).order(1, 2, 3, 4)).should == "1\t2\t1\t2\n1\t2\t3\t4\n3\t4\t1\t2\n3\t4\t3\t4\n"
1060
+ end
1061
+
1062
+ specify "with a block and no options should yield each row as a string in text format" do
1063
+ buf = []
1064
+ @db.copy_table(:test_copy){|b| buf << b}
1065
+ buf.should == ["1\t2\n", "3\t4\n"]
1066
+ end
1067
+
1068
+ specify "with a block and :format=>:csv should yield each row as a string in csv format" do
1069
+ buf = []
1070
+ @db.copy_table(:test_copy, :format=>:csv){|b| buf << b}
1071
+ buf.should == ["1,2\n", "3,4\n"]
1072
+ end
1073
+
1074
+ specify "should work fine when using a block that is terminated early with a following copy_table" do
1075
+ buf = []
1076
+ proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
1077
+ buf.should == ["1,2\n"]
1078
+ buf.clear
1079
+ proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
1080
+ buf.should == ["1,2\n"]
1081
+ buf.clear
1082
+ @db.copy_table(:test_copy){|b| buf << b}
1083
+ buf.should == ["1\t2\n", "3\t4\n"]
1084
+ end
1085
+
1086
+ specify "should work fine when using a block that is terminated early with a following regular query" do
1087
+ buf = []
1088
+ proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; break}}.should raise_error(Sequel::DatabaseDisconnectError)
1089
+ buf.should == ["1,2\n"]
1090
+ buf.clear
1091
+ proc{@db.copy_table(:test_copy, :format=>:csv){|b| buf << b; raise ArgumentError}}.should raise_error(Sequel::DatabaseDisconnectError)
1092
+ buf.should == ["1,2\n"]
1093
+ @db[:test_copy].select_order_map(:x).should == [1, 3]
1094
+ end
1095
+ end
1009
1096
  end
@@ -10,6 +10,11 @@ begin
10
10
  rescue LoadError
11
11
  end
12
12
 
13
+ if ENV['SEQUEL_COLUMNS_INTROSPECTION']
14
+ Sequel.extension :columns_introspection
15
+ Sequel::Dataset.introspect_all_columns
16
+ end
17
+
13
18
  class Sequel::Database
14
19
  def log_duration(duration, message)
15
20
  log_info(message)
@@ -31,6 +36,7 @@ end
31
36
  end
32
37
 
33
38
  def self.cspecify(message, *checked, &block)
39
+ return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
34
40
  pending = false
35
41
  checked.each do |c|
36
42
  case c
@@ -66,6 +66,17 @@ describe "An SQLite database" do
66
66
  @db[:fk].all.should == [{:id=>1, :parent_id=>2}]
67
67
  end
68
68
 
69
+ specify "should support a use_timestamp_timezones setting" do
70
+ @db.create_table!(:time){Time :time}
71
+ @db[:time].insert(Time.now)
72
+ @db[:time].get(:time.cast_string).should =~ /[-+]\d\d\d\d\z/
73
+ @db.use_timestamp_timezones = false
74
+ @db[:time].delete
75
+ @db[:time].insert(Time.now)
76
+ @db[:time].get(:time.cast_string).should_not =~ /[-+]\d\d\d\d\z/
77
+ @db.use_timestamp_timezones = true
78
+ end
79
+
69
80
  specify "should provide a list of existing tables" do
70
81
  @db.drop_table(:testing) rescue nil
71
82
  @db.tables.should be_a_kind_of(Array)