viking-sequel 3.10.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 (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. metadata +346 -0
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'logger'
3
+ unless Object.const_defined?('Sequel')
4
+ $:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
5
+ require 'sequel'
6
+ Sequel.quote_identifiers = false
7
+ end
8
+ begin
9
+ require File.join(File.dirname(File.dirname(__FILE__)), 'spec_config.rb')
10
+ rescue LoadError
11
+ end
12
+
13
+ class Sequel::Database
14
+ def log_duration(duration, message)
15
+ log_info(message)
16
+ end
17
+ end
18
+
19
+ class Spec::Example::ExampleGroup
20
+ def log
21
+ begin
22
+ INTEGRATION_DB.loggers << Logger.new(STDOUT)
23
+ yield
24
+ ensure
25
+ INTEGRATION_DB.loggers.pop
26
+ end
27
+ end
28
+
29
+ def self.log_specify(message, &block)
30
+ specify(message){log{instance_eval(&block)}}
31
+ end
32
+
33
+ def self.cspecify(message, *checked, &block)
34
+ pending = false
35
+ checked.each do |c|
36
+ case c
37
+ when INTEGRATION_DB.class.adapter_scheme
38
+ pending = c
39
+ when Proc
40
+ pending = c if c.first.call(INTEGRATION_DB)
41
+ when Array
42
+ pending = c if c.first == INTEGRATION_DB.class.adapter_scheme && c.last == INTEGRATION_DB.call(INTEGRATION_DB)
43
+ end
44
+ end
45
+ if pending
46
+ specify(message){pending("Not yet working on #{Array(pending).join(', ')}", &block)}
47
+ else
48
+ specify(message, &block)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,432 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper.rb')
2
+
3
+ unless defined?(SQLITE_DB)
4
+ SQLITE_URL = 'sqlite:/' unless defined? SQLITE_URL
5
+ SQLITE_DB = Sequel.connect(ENV['SEQUEL_SQLITE_SPEC_DB']||SQLITE_URL)
6
+ end
7
+ INTEGRATION_DB = SQLITE_DB unless defined?(INTEGRATION_DB)
8
+
9
+ context "An SQLite database" do
10
+ before do
11
+ @db = SQLITE_DB
12
+ end
13
+ after do
14
+ Sequel.datetime_class = Time
15
+ end
16
+
17
+ if SQLITE_DB.auto_vacuum == :none
18
+ specify "should support getting pragma values" do
19
+ @db.pragma_get(:auto_vacuum).to_s.should == '0'
20
+ end
21
+
22
+ specify "should support setting pragma values" do
23
+ @db.pragma_set(:auto_vacuum, '1')
24
+ @db.pragma_get(:auto_vacuum).to_s.should == '1'
25
+ @db.pragma_set(:auto_vacuum, '2')
26
+ @db.pragma_get(:auto_vacuum).to_s.should == '2'
27
+ end
28
+
29
+ specify "should support getting and setting the auto_vacuum pragma" do
30
+ @db.auto_vacuum = :full
31
+ @db.auto_vacuum.should == :full
32
+ @db.auto_vacuum = :incremental
33
+ @db.auto_vacuum.should == :incremental
34
+
35
+ proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
36
+ end
37
+ end
38
+
39
+ specify "should provide the SQLite version as an integer" do
40
+ @db.sqlite_version.should be_a_kind_of(Integer)
41
+ end
42
+
43
+ specify "should support setting and getting the foreign_keys pragma" do
44
+ (@db.sqlite_version >= 30619 ? [true, false] : [nil]).should include(@db.foreign_keys)
45
+ @db.foreign_keys = true
46
+ @db.foreign_keys = false
47
+ end
48
+
49
+ if SQLITE_DB.sqlite_version >= 30619
50
+ specify "should enforce foreign key integrity if foreign_keys pragma is set" do
51
+ @db.foreign_keys = true
52
+ @db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
53
+ @db[:fk].insert(1, nil)
54
+ @db[:fk].insert(2, 1)
55
+ @db[:fk].insert(3, 3)
56
+ proc{@db[:fk].insert(4, 5)}.should raise_error(Sequel::Error)
57
+ end
58
+ end
59
+
60
+ specify "should not enforce foreign key integrity if foreign_keys pragma is unset" do
61
+ @db.foreign_keys = false
62
+ @db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
63
+ @db[:fk].insert(1, 2)
64
+ @db[:fk].all.should == [{:id=>1, :parent_id=>2}]
65
+ end
66
+
67
+ specify "should provide a list of existing tables" do
68
+ @db.drop_table(:testing) rescue nil
69
+ @db.tables.should be_a_kind_of(Array)
70
+ @db.tables.should_not include(:testing)
71
+ @db.create_table! :testing do
72
+ text :name
73
+ end
74
+ @db.tables.should include(:testing)
75
+ end
76
+
77
+ specify "should support getting and setting the synchronous pragma" do
78
+ @db.synchronous = :off
79
+ @db.synchronous.should == :off
80
+ @db.synchronous = :normal
81
+ @db.synchronous.should == :normal
82
+ @db.synchronous = :full
83
+ @db.synchronous.should == :full
84
+
85
+ proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
86
+ end
87
+
88
+ specify "should support getting and setting the temp_store pragma" do
89
+ @db.temp_store = :default
90
+ @db.temp_store.should == :default
91
+ @db.temp_store = :file
92
+ @db.temp_store.should == :file
93
+ @db.temp_store = :memory
94
+ @db.temp_store.should == :memory
95
+
96
+ proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
97
+ end
98
+
99
+ cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite do
100
+ @db.create_table!(:time){timestamp :t; datetime :d}
101
+ t1 = Time.at(1)
102
+ @db[:time] << {:t => t1, :d => t1.to_i}
103
+ @db[:time] << {:t => t1.to_i, :d => t1}
104
+ @db[:time].map(:t).should == [t1, t1]
105
+ @db[:time].map(:d).should == [t1, t1]
106
+ Sequel.datetime_class = DateTime
107
+ t2 = Sequel.string_to_datetime(t1.iso8601)
108
+ @db[:time].map(:t).should == [t2, t2]
109
+ @db[:time].map(:d).should == [t2, t2]
110
+ end
111
+
112
+ specify "should support sequential primary keys" do
113
+ @db.create_table!(:with_pk) {primary_key :id; text :name}
114
+ @db[:with_pk] << {:name => 'abc'}
115
+ @db[:with_pk] << {:name => 'def'}
116
+ @db[:with_pk] << {:name => 'ghi'}
117
+ @db[:with_pk].order(:name).all.should == [
118
+ {:id => 1, :name => 'abc'},
119
+ {:id => 2, :name => 'def'},
120
+ {:id => 3, :name => 'ghi'}
121
+ ]
122
+ end
123
+
124
+ specify "should correctly parse the schema" do
125
+ @db.create_table!(:time2) {timestamp :t}
126
+ @db.schema(:time2, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"timestamp", :primary_key=>false}]]
127
+ end
128
+ end
129
+
130
+ context "An SQLite dataset" do
131
+ before do
132
+ @d = SQLITE_DB[:items]
133
+ end
134
+
135
+ specify "should handle string pattern matches correctly" do
136
+ @d.literal(:x.like('a')).should == "(x LIKE 'a')"
137
+ @d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
138
+ @d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
139
+ @d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
140
+ end
141
+
142
+ specify "should raise errors if given a regexp pattern match" do
143
+ proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
144
+ proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
145
+ proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
146
+ proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
147
+ end
148
+ end
149
+
150
+ context "An SQLite numeric column" do
151
+ specify "should handle and return BigDecimal values" do
152
+ SQLITE_DB.create_table!(:d){numeric :d}
153
+ d = SQLITE_DB[:d]
154
+ d.insert(:d=>BigDecimal.new('80.0'))
155
+ d.insert(:d=>BigDecimal.new('NaN'))
156
+ d.insert(:d=>BigDecimal.new('Infinity'))
157
+ d.insert(:d=>BigDecimal.new('-Infinity'))
158
+ ds = d.all
159
+ ds.shift.should == {:d=>BigDecimal.new('80.0')}
160
+ ds.map{|x| x[:d].to_s}.should == %w'NaN Infinity -Infinity'
161
+ end
162
+ end
163
+
164
+ context "An SQLite dataset AS clause" do
165
+ specify "should use a string literal for :col___alias" do
166
+ SQLITE_DB.literal(:c___a).should == "c AS 'a'"
167
+ end
168
+
169
+ specify "should use a string literal for :table__col___alias" do
170
+ SQLITE_DB.literal(:t__c___a).should == "t.c AS 'a'"
171
+ end
172
+
173
+ specify "should use a string literal for :column.as(:alias)" do
174
+ SQLITE_DB.literal(:c.as(:a)).should == "c AS 'a'"
175
+ end
176
+
177
+ specify "should use a string literal in the SELECT clause" do
178
+ SQLITE_DB[:t].select(:c___a).sql.should == "SELECT c AS 'a' FROM t"
179
+ end
180
+
181
+ specify "should use a string literal in the FROM clause" do
182
+ SQLITE_DB[:t___a].sql.should == "SELECT * FROM t AS 'a'"
183
+ end
184
+
185
+ specify "should use a string literal in the JOIN clause" do
186
+ SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM t NATURAL JOIN j AS 'a'"
187
+ end
188
+ end
189
+
190
+ context "SQLite::Dataset#delete" do
191
+ before do
192
+ SQLITE_DB.create_table! :items do
193
+ primary_key :id
194
+ String :name
195
+ Float :value
196
+ end
197
+ @d = SQLITE_DB[:items]
198
+ @d.delete # remove all records
199
+ @d << {:name => 'abc', :value => 1.23}
200
+ @d << {:name => 'def', :value => 4.56}
201
+ @d << {:name => 'ghi', :value => 7.89}
202
+ end
203
+
204
+ specify "should return the number of records affected when filtered" do
205
+ @d.count.should == 3
206
+ @d.filter(:value.sql_number < 3).delete.should == 1
207
+ @d.count.should == 2
208
+
209
+ @d.filter(:value.sql_number < 3).delete.should == 0
210
+ @d.count.should == 2
211
+ end
212
+
213
+ specify "should return the number of records affected when unfiltered" do
214
+ @d.count.should == 3
215
+ @d.delete.should == 3
216
+ @d.count.should == 0
217
+
218
+ @d.delete.should == 0
219
+ end
220
+ end
221
+
222
+ context "SQLite::Dataset#update" do
223
+ before do
224
+ SQLITE_DB.create_table! :items do
225
+ primary_key :id
226
+ String :name
227
+ Float :value
228
+ end
229
+ @d = SQLITE_DB[:items]
230
+ @d.delete # remove all records
231
+ @d << {:name => 'abc', :value => 1.23}
232
+ @d << {:name => 'def', :value => 4.56}
233
+ @d << {:name => 'ghi', :value => 7.89}
234
+ end
235
+
236
+ specify "should return the number of records affected" do
237
+ @d.filter(:name => 'abc').update(:value => 2).should == 1
238
+
239
+ @d.update(:value => 10).should == 3
240
+
241
+ @d.filter(:name => 'xxx').update(:value => 23).should == 0
242
+ end
243
+ end
244
+
245
+ context "SQLite dataset" do
246
+ before do
247
+ SQLITE_DB.create_table! :test do
248
+ primary_key :id
249
+ String :name
250
+ Float :value
251
+ end
252
+ SQLITE_DB.create_table! :items do
253
+ primary_key :id
254
+ String :name
255
+ Float :value
256
+ end
257
+ @d = SQLITE_DB[:items]
258
+ @d << {:name => 'abc', :value => 1.23}
259
+ @d << {:name => 'def', :value => 4.56}
260
+ @d << {:name => 'ghi', :value => 7.89}
261
+ end
262
+ after do
263
+ SQLITE_DB.drop_table(:test, :items)
264
+ end
265
+
266
+ specify "should be able to insert from a subquery" do
267
+ SQLITE_DB[:test] << @d
268
+ SQLITE_DB[:test].count.should == 3
269
+ SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
270
+ @d.select(:name, :value).order(:value).to_a
271
+ end
272
+
273
+ specify "should support #explain" do
274
+ SQLITE_DB[:test].explain.should be_a_kind_of(Array)
275
+ end
276
+
277
+ specify "should have #explain work when identifier_output_method is modified" do
278
+ ds = SQLITE_DB[:test]
279
+ ds.identifier_output_method = :upcase
280
+ ds.explain.should be_a_kind_of(Array)
281
+ end
282
+ end
283
+
284
+ context "A SQLite database" do
285
+ before do
286
+ @db = SQLITE_DB
287
+ @db.create_table! :test2 do
288
+ text :name
289
+ integer :value
290
+ end
291
+ end
292
+
293
+ specify "should support add_column operations" do
294
+ @db.add_column :test2, :xyz, :text
295
+
296
+ @db[:test2].columns.should == [:name, :value, :xyz]
297
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz=>'000'}
298
+ @db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
299
+ end
300
+
301
+ specify "should support drop_column operations" do
302
+ @db.drop_column :test2, :value
303
+ @db[:test2].columns.should == [:name]
304
+ @db[:test2] << {:name => 'mmm'}
305
+ @db[:test2].first.should == {:name => 'mmm'}
306
+ end
307
+
308
+ specify "should support drop_column operations in a transaction" do
309
+ @db.transaction{@db.drop_column :test2, :value}
310
+ @db[:test2].columns.should == [:name]
311
+ @db[:test2] << {:name => 'mmm'}
312
+ @db[:test2].first.should == {:name => 'mmm'}
313
+ end
314
+
315
+ specify "should keep column attributes when dropping a column" do
316
+ @db.create_table! :test3 do
317
+ primary_key :id
318
+ text :name
319
+ integer :value
320
+ end
321
+
322
+ # This lame set of additions and deletions are to test that the primary keys
323
+ # don't get messed up when we recreate the database.
324
+ @db[:test3] << { :name => "foo", :value => 1}
325
+ @db[:test3] << { :name => "foo", :value => 2}
326
+ @db[:test3] << { :name => "foo", :value => 3}
327
+ @db[:test3].filter(:id => 2).delete
328
+
329
+ @db.drop_column :test3, :value
330
+
331
+ @db['PRAGMA table_info(?)', :test3][:id][:pk].to_i.should == 1
332
+ @db[:test3].select(:id).all.should == [{:id => 1}, {:id => 3}]
333
+ end
334
+
335
+ specify "should support rename_column operations" do
336
+ @db[:test2].delete
337
+ @db.add_column :test2, :xyz, :text
338
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
339
+
340
+ @db[:test2].columns.should == [:name, :value, :xyz]
341
+ @db.rename_column :test2, :xyz, :zyx, :type => :text
342
+ @db[:test2].columns.should == [:name, :value, :zyx]
343
+ @db[:test2].first[:zyx].should == 'qqqq'
344
+ @db[:test2].count.should eql(1)
345
+ end
346
+
347
+ specify "should preserve defaults when dropping or renaming columns" do
348
+ @db.create_table! :test3 do
349
+ String :s, :default=>'a'
350
+ Integer :i
351
+ end
352
+
353
+ @db[:test3].insert
354
+ @db[:test3].first[:s].should == 'a'
355
+ @db[:test3].delete
356
+ @db.drop_column :test3, :i
357
+ @db[:test3].insert
358
+ @db[:test3].first[:s].should == 'a'
359
+ @db[:test3].delete
360
+ @db.rename_column :test3, :s, :t
361
+ @db[:test3].insert
362
+ @db[:test3].first[:t].should == 'a'
363
+ @db[:test3].delete
364
+ end
365
+
366
+ specify "should handle quoted tables when dropping or renaming columns" do
367
+ @db.quote_identifiers = true
368
+ table_name = "T T"
369
+ @db.drop_table(table_name) rescue nil
370
+ @db.create_table! table_name do
371
+ Integer :"s s"
372
+ Integer :"i i"
373
+ end
374
+
375
+ @db.from(table_name).insert(:"s s"=>1, :"i i"=>2)
376
+ @db.from(table_name).all.should == [{:"s s"=>1, :"i i"=>2}]
377
+ @db.drop_column table_name, :"i i"
378
+ @db.from(table_name).all.should == [{:"s s"=>1}]
379
+ @db.rename_column table_name, :"s s", :"t t"
380
+ @db.from(table_name).all.should == [{:"t t"=>1}]
381
+ end
382
+
383
+ specify "should choose a temporary table name that isn't already used when dropping or renaming columns" do
384
+ sqls = []
385
+ @db.loggers << (l=Class.new{define_method(:info){|sql| sqls << sql}}.new)
386
+ @db.create_table! :test3 do
387
+ Integer :h
388
+ Integer :i
389
+ end
390
+ @db.create_table! :test3_backup0 do
391
+ Integer :j
392
+ end
393
+ @db.create_table! :test3_backup1 do
394
+ Integer :k
395
+ end
396
+
397
+ @db[:test3].columns.should == [:h, :i]
398
+ @db[:test3_backup0].columns.should == [:j]
399
+ @db[:test3_backup1].columns.should == [:k]
400
+ sqls.clear
401
+ @db.drop_column(:test3, :i)
402
+ sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup2/}.should == true
403
+ sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[01]/}.should == false
404
+ @db[:test3].columns.should == [:h]
405
+ @db[:test3_backup0].columns.should == [:j]
406
+ @db[:test3_backup1].columns.should == [:k]
407
+
408
+ @db.create_table! :test3_backup2 do
409
+ Integer :l
410
+ end
411
+
412
+ sqls.clear
413
+ @db.rename_column(:test3, :h, :i)
414
+ sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup3/}.should == true
415
+ sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[012]/}.should == false
416
+ @db[:test3].columns.should == [:i]
417
+ @db[:test3_backup0].columns.should == [:j]
418
+ @db[:test3_backup1].columns.should == [:k]
419
+ @db[:test3_backup2].columns.should == [:l]
420
+ @db.loggers.delete(l)
421
+ end
422
+
423
+ specify "should support add_index" do
424
+ @db.add_index :test2, :value, :unique => true
425
+ @db.add_index :test2, [:name, :value]
426
+ end
427
+
428
+ specify "should support drop_index" do
429
+ @db.add_index :test2, :value, :unique => true
430
+ @db.drop_index :test2, :value
431
+ end
432
+ end