epugh-sequel 0.0.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.
- data/README.rdoc +652 -0
- data/VERSION.yml +4 -0
- data/bin/sequel +104 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +85 -0
- data/lib/sequel/adapters/db2.rb +132 -0
- data/lib/sequel/adapters/dbi.rb +101 -0
- data/lib/sequel/adapters/do.rb +197 -0
- data/lib/sequel/adapters/do/mysql.rb +38 -0
- data/lib/sequel/adapters/do/postgres.rb +92 -0
- data/lib/sequel/adapters/do/sqlite.rb +31 -0
- data/lib/sequel/adapters/firebird.rb +307 -0
- data/lib/sequel/adapters/informix.rb +75 -0
- data/lib/sequel/adapters/jdbc.rb +485 -0
- data/lib/sequel/adapters/jdbc/h2.rb +62 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +56 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +23 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +101 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +43 -0
- data/lib/sequel/adapters/mysql.rb +370 -0
- data/lib/sequel/adapters/odbc.rb +184 -0
- data/lib/sequel/adapters/openbase.rb +57 -0
- data/lib/sequel/adapters/oracle.rb +140 -0
- data/lib/sequel/adapters/postgres.rb +453 -0
- data/lib/sequel/adapters/shared/mssql.rb +93 -0
- data/lib/sequel/adapters/shared/mysql.rb +341 -0
- data/lib/sequel/adapters/shared/oracle.rb +62 -0
- data/lib/sequel/adapters/shared/postgres.rb +743 -0
- data/lib/sequel/adapters/shared/progress.rb +34 -0
- data/lib/sequel/adapters/shared/sqlite.rb +263 -0
- data/lib/sequel/adapters/sqlite.rb +243 -0
- data/lib/sequel/adapters/utils/date_format.rb +21 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +75 -0
- data/lib/sequel/adapters/utils/unsupported.rb +62 -0
- data/lib/sequel/connection_pool.rb +258 -0
- data/lib/sequel/core.rb +204 -0
- data/lib/sequel/core_sql.rb +185 -0
- data/lib/sequel/database.rb +687 -0
- data/lib/sequel/database/schema_generator.rb +324 -0
- data/lib/sequel/database/schema_methods.rb +164 -0
- data/lib/sequel/database/schema_sql.rb +324 -0
- data/lib/sequel/dataset.rb +422 -0
- data/lib/sequel/dataset/convenience.rb +237 -0
- data/lib/sequel/dataset/prepared_statements.rb +220 -0
- data/lib/sequel/dataset/sql.rb +1105 -0
- data/lib/sequel/deprecated.rb +529 -0
- data/lib/sequel/exceptions.rb +44 -0
- data/lib/sequel/extensions/blank.rb +42 -0
- data/lib/sequel/extensions/inflector.rb +288 -0
- data/lib/sequel/extensions/pagination.rb +96 -0
- data/lib/sequel/extensions/pretty_table.rb +78 -0
- data/lib/sequel/extensions/query.rb +48 -0
- data/lib/sequel/extensions/string_date_time.rb +47 -0
- data/lib/sequel/metaprogramming.rb +44 -0
- data/lib/sequel/migration.rb +212 -0
- data/lib/sequel/model.rb +142 -0
- data/lib/sequel/model/association_reflection.rb +263 -0
- data/lib/sequel/model/associations.rb +1024 -0
- data/lib/sequel/model/base.rb +911 -0
- data/lib/sequel/model/deprecated.rb +188 -0
- data/lib/sequel/model/deprecated_hooks.rb +103 -0
- data/lib/sequel/model/deprecated_inflector.rb +335 -0
- data/lib/sequel/model/deprecated_validations.rb +384 -0
- data/lib/sequel/model/errors.rb +37 -0
- data/lib/sequel/model/exceptions.rb +7 -0
- data/lib/sequel/model/inflections.rb +230 -0
- data/lib/sequel/model/plugins.rb +74 -0
- data/lib/sequel/object_graph.rb +230 -0
- data/lib/sequel/plugins/caching.rb +122 -0
- data/lib/sequel/plugins/hook_class_methods.rb +122 -0
- data/lib/sequel/plugins/schema.rb +53 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
- data/lib/sequel/plugins/validation_class_methods.rb +373 -0
- data/lib/sequel/sql.rb +854 -0
- data/lib/sequel/version.rb +11 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/ado_spec.rb +46 -0
- data/spec/adapters/firebird_spec.rb +376 -0
- data/spec/adapters/informix_spec.rb +96 -0
- data/spec/adapters/mysql_spec.rb +875 -0
- data/spec/adapters/oracle_spec.rb +272 -0
- data/spec/adapters/postgres_spec.rb +692 -0
- data/spec/adapters/spec_helper.rb +10 -0
- data/spec/adapters/sqlite_spec.rb +550 -0
- data/spec/core/connection_pool_spec.rb +526 -0
- data/spec/core/core_ext_spec.rb +156 -0
- data/spec/core/core_sql_spec.rb +528 -0
- data/spec/core/database_spec.rb +1214 -0
- data/spec/core/dataset_spec.rb +3513 -0
- data/spec/core/expression_filters_spec.rb +363 -0
- data/spec/core/migration_spec.rb +261 -0
- data/spec/core/object_graph_spec.rb +280 -0
- data/spec/core/pretty_table_spec.rb +58 -0
- data/spec/core/schema_generator_spec.rb +167 -0
- data/spec/core/schema_spec.rb +778 -0
- data/spec/core/spec_helper.rb +82 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/caching_spec.rb +201 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/inflector_spec.rb +122 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/schema_spec.rb +111 -0
- data/spec/extensions/single_table_inheritance_spec.rb +53 -0
- data/spec/extensions/spec_helper.rb +90 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/validation_class_methods_spec.rb +1054 -0
- data/spec/integration/dataset_test.rb +160 -0
- data/spec/integration/eager_loader_test.rb +683 -0
- data/spec/integration/prepared_statement_test.rb +130 -0
- data/spec/integration/schema_test.rb +183 -0
- data/spec/integration/spec_helper.rb +75 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +93 -0
- data/spec/model/associations_spec.rb +1780 -0
- data/spec/model/base_spec.rb +494 -0
- data/spec/model/caching_spec.rb +217 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1165 -0
- data/spec/model/hooks_spec.rb +472 -0
- data/spec/model/inflector_spec.rb +126 -0
- data/spec/model/model_spec.rb +588 -0
- data/spec/model/plugins_spec.rb +142 -0
- data/spec/model/record_spec.rb +1243 -0
- data/spec/model/schema_spec.rb +92 -0
- data/spec/model/spec_helper.rb +124 -0
- data/spec/model/validations_spec.rb +1080 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +202 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
unless Object.const_defined?('Sequel')
|
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
4
|
+
require 'sequel/core'
|
|
5
|
+
Sequel.quote_identifiers = false
|
|
6
|
+
end
|
|
7
|
+
begin
|
|
8
|
+
require File.join(File.dirname(__FILE__), '../spec_config.rb')
|
|
9
|
+
rescue LoadError
|
|
10
|
+
end
|
|
@@ -0,0 +1,550 @@
|
|
|
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
|
+
|
|
8
|
+
context "An SQLite database" do
|
|
9
|
+
before do
|
|
10
|
+
@db = SQLITE_DB
|
|
11
|
+
end
|
|
12
|
+
after do
|
|
13
|
+
Sequel.datetime_class = Time
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if SQLITE_DB.auto_vacuum == :none
|
|
17
|
+
specify "should support getting pragma values" do
|
|
18
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '0'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
specify "should support setting pragma values" do
|
|
22
|
+
@db.pragma_set(:auto_vacuum, '1')
|
|
23
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '1'
|
|
24
|
+
@db.pragma_set(:auto_vacuum, '2')
|
|
25
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '2'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
specify "should support getting and setting the auto_vacuum pragma" do
|
|
29
|
+
@db.auto_vacuum = :full
|
|
30
|
+
@db.auto_vacuum.should == :full
|
|
31
|
+
@db.auto_vacuum = :incremental
|
|
32
|
+
@db.auto_vacuum.should == :incremental
|
|
33
|
+
|
|
34
|
+
proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
specify "should provide a list of existing tables" do
|
|
39
|
+
@db.drop_table(:testing) rescue nil
|
|
40
|
+
@db.tables.should be_a_kind_of(Array)
|
|
41
|
+
@db.tables.should_not include(:testing)
|
|
42
|
+
@db.create_table! :testing do
|
|
43
|
+
text :name
|
|
44
|
+
end
|
|
45
|
+
@db.tables.should include(:testing)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
specify "should support getting and setting the synchronous pragma" do
|
|
49
|
+
@db.synchronous = :off
|
|
50
|
+
@db.synchronous.should == :off
|
|
51
|
+
@db.synchronous = :normal
|
|
52
|
+
@db.synchronous.should == :normal
|
|
53
|
+
@db.synchronous = :full
|
|
54
|
+
@db.synchronous.should == :full
|
|
55
|
+
|
|
56
|
+
proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
specify "should support getting and setting the temp_store pragma" do
|
|
60
|
+
@db.temp_store = :default
|
|
61
|
+
@db.temp_store.should == :default
|
|
62
|
+
@db.temp_store = :file
|
|
63
|
+
@db.temp_store.should == :file
|
|
64
|
+
@db.temp_store = :memory
|
|
65
|
+
@db.temp_store.should == :memory
|
|
66
|
+
|
|
67
|
+
proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
specify "should be able to execute transactions" do
|
|
71
|
+
@db.transaction do
|
|
72
|
+
@db.create_table!(:t) {text :name}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@db.tables.should include(:t)
|
|
76
|
+
|
|
77
|
+
proc {@db.transaction do
|
|
78
|
+
@db.create_table!(:u) {text :name}
|
|
79
|
+
raise ArgumentError
|
|
80
|
+
end}.should raise_error(ArgumentError)
|
|
81
|
+
# no commit
|
|
82
|
+
@db.tables.should_not include(:u)
|
|
83
|
+
|
|
84
|
+
proc {@db.transaction do
|
|
85
|
+
@db.create_table!(:v) {text :name}
|
|
86
|
+
raise Sequel::Error::Rollback
|
|
87
|
+
end}.should_not raise_error
|
|
88
|
+
# no commit
|
|
89
|
+
@db.tables.should_not include(:r)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
specify "should support nested transactions" do
|
|
93
|
+
@db.transaction do
|
|
94
|
+
@db.transaction do
|
|
95
|
+
@db.create_table!(:t) {text :name}
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@db.tables.should include(:t)
|
|
100
|
+
|
|
101
|
+
proc {@db.transaction do
|
|
102
|
+
@db.create_table!(:v) {text :name}
|
|
103
|
+
@db.transaction do
|
|
104
|
+
raise Sequel::Error::Rollback # should roll back the top-level transaction
|
|
105
|
+
end
|
|
106
|
+
end}.should_not raise_error
|
|
107
|
+
# no commit
|
|
108
|
+
@db.tables.should_not include(:v)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
specify "should handle returning inside of transaction by committing" do
|
|
112
|
+
@db.create_table!(:items2){text :name}
|
|
113
|
+
def @db.ret_commit
|
|
114
|
+
transaction do
|
|
115
|
+
self[:items2] << {:name => 'abc'}
|
|
116
|
+
return
|
|
117
|
+
self[:items2] << {:name => 'd'}
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
@db[:items2].count.should == 0
|
|
121
|
+
@db.ret_commit
|
|
122
|
+
@db[:items2].count.should == 1
|
|
123
|
+
@db.ret_commit
|
|
124
|
+
@db[:items2].count.should == 2
|
|
125
|
+
proc do
|
|
126
|
+
@db.transaction do
|
|
127
|
+
raise Interrupt, 'asdf'
|
|
128
|
+
end
|
|
129
|
+
end.should raise_error(Interrupt)
|
|
130
|
+
|
|
131
|
+
@db[:items2].count.should == 2
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
specify "should support timestamps and datetimes and respect datetime_class" do
|
|
135
|
+
@db.create_table!(:time){timestamp :t; datetime :d}
|
|
136
|
+
t1 = Time.at(1)
|
|
137
|
+
@db[:time] << {:t => t1, :d => t1.to_i}
|
|
138
|
+
@db[:time] << {:t => t1.to_i, :d => t1}
|
|
139
|
+
@db[:time].map(:t).should == [t1, t1]
|
|
140
|
+
@db[:time].map(:d).should == [t1, t1]
|
|
141
|
+
Sequel.datetime_class = DateTime
|
|
142
|
+
t2 = Sequel.string_to_datetime(t1.iso8601)
|
|
143
|
+
@db[:time].map(:t).should == [t2, t2]
|
|
144
|
+
@db[:time].map(:d).should == [t2, t2]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
specify "should support sequential primary keys" do
|
|
148
|
+
@db.create_table!(:with_pk) {primary_key :id; text :name}
|
|
149
|
+
@db[:with_pk] << {:name => 'abc'}
|
|
150
|
+
@db[:with_pk] << {:name => 'def'}
|
|
151
|
+
@db[:with_pk] << {:name => 'ghi'}
|
|
152
|
+
@db[:with_pk].order(:name).all.should == [
|
|
153
|
+
{:id => 1, :name => 'abc'},
|
|
154
|
+
{:id => 2, :name => 'def'},
|
|
155
|
+
{:id => 3, :name => 'ghi'}
|
|
156
|
+
]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
specify "should catch invalid SQL errors and raise them as Error" do
|
|
160
|
+
proc {@db.execute 'blah blah'}.should raise_error(Sequel::Error)
|
|
161
|
+
proc {@db.execute_insert 'blah blah'}.should raise_error(Sequel::Error)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
specify "should not swallow non-SQLite based exceptions" do
|
|
165
|
+
proc {@db.pool.hold{raise Interrupt, "test"}}.should raise_error(Interrupt)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
specify "should correctly parse the schema" do
|
|
169
|
+
@db.create_table!(:time2) {timestamp :t}
|
|
170
|
+
@db.schema(:time2, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :default=>nil, :db_type=>"timestamp", :primary_key=>false}]]
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
context "An SQLite dataset" do
|
|
175
|
+
setup do
|
|
176
|
+
SQLITE_DB.create_table! :items do
|
|
177
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
178
|
+
text :name
|
|
179
|
+
float :value
|
|
180
|
+
end
|
|
181
|
+
@d = SQLITE_DB[:items]
|
|
182
|
+
@d.delete # remove all records
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
specify "should return the correct records" do
|
|
186
|
+
@d.to_a.should == []
|
|
187
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
188
|
+
@d << {:name => 'abc', :value => 4.56}
|
|
189
|
+
@d << {:name => 'def', :value => 7.89}
|
|
190
|
+
@d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
|
|
191
|
+
{:name => 'abc', :value => 1.23},
|
|
192
|
+
{:name => 'abc', :value => 4.56},
|
|
193
|
+
{:name => 'def', :value => 7.89}
|
|
194
|
+
]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
specify "should return the correct record count" do
|
|
198
|
+
@d.count.should == 0
|
|
199
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
200
|
+
@d << {:name => 'abc', :value => 4.56}
|
|
201
|
+
@d << {:name => 'def', :value => 7.89}
|
|
202
|
+
@d.count.should == 3
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
specify "should return the last inserted id when inserting records" do
|
|
206
|
+
id = @d << {:name => 'abc', :value => 1.23}
|
|
207
|
+
id.should == @d.first[:id]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
specify "should update records correctly" do
|
|
211
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
212
|
+
@d << {:name => 'abc', :value => 4.56}
|
|
213
|
+
@d << {:name => 'def', :value => 7.89}
|
|
214
|
+
@d.filter(:name => 'abc').update(:value => 5.3)
|
|
215
|
+
|
|
216
|
+
# the third record should stay the same
|
|
217
|
+
@d[:name => 'def'][:value].should == 7.89
|
|
218
|
+
@d.filter(:value => 5.3).count.should == 2
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
specify "should delete records correctly" do
|
|
222
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
223
|
+
@d << {:name => 'abc', :value => 4.56}
|
|
224
|
+
@d << {:name => 'def', :value => 7.89}
|
|
225
|
+
@d.filter(:name => 'abc').delete
|
|
226
|
+
|
|
227
|
+
@d.count.should == 1
|
|
228
|
+
@d.first[:name].should == 'def'
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
specify "should handle string pattern matches correctly" do
|
|
232
|
+
@d.literal(:x.like('a')).should == "(x LIKE 'a')"
|
|
233
|
+
@d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
|
|
234
|
+
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
|
235
|
+
@d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
specify "should raise errors if given a regexp pattern match" do
|
|
239
|
+
proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
|
|
240
|
+
proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
|
|
241
|
+
proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
|
|
242
|
+
proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context "An SQLite numeric column" do
|
|
247
|
+
specify "should handle and return BigDecimal values" do
|
|
248
|
+
SQLITE_DB.create_table!(:d){numeric :d}
|
|
249
|
+
d = SQLITE_DB[:d]
|
|
250
|
+
d.insert(:d=>BigDecimal.new('80.0'))
|
|
251
|
+
d.insert(:d=>BigDecimal.new('NaN'))
|
|
252
|
+
d.insert(:d=>BigDecimal.new('Infinity'))
|
|
253
|
+
d.insert(:d=>BigDecimal.new('-Infinity'))
|
|
254
|
+
ds = d.all
|
|
255
|
+
ds.shift.should == {:d=>BigDecimal.new('80.0')}
|
|
256
|
+
ds.map{|x| x[:d].to_s}.should == %w'NaN Infinity -Infinity'
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
context "An SQLite dataset AS clause" do
|
|
261
|
+
specify "should use a string literal for :col___alias" do
|
|
262
|
+
SQLITE_DB.literal(:c___a).should == "c AS 'a'"
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
specify "should use a string literal for :table__col___alias" do
|
|
266
|
+
SQLITE_DB.literal(:t__c___a).should == "t.c AS 'a'"
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
specify "should use a string literal for :column.as(:alias)" do
|
|
270
|
+
SQLITE_DB.literal(:c.as(:a)).should == "c AS 'a'"
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
specify "should use a string literal in the SELECT clause" do
|
|
274
|
+
SQLITE_DB[:t].select(:c___a).sql.should == "SELECT c AS 'a' FROM t"
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
specify "should use a string literal in the FROM clause" do
|
|
278
|
+
SQLITE_DB[:t___a].sql.should == "SELECT * FROM t AS 'a'"
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
specify "should use a string literal in the JOIN clause" do
|
|
282
|
+
SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM t NATURAL JOIN j AS 'a'"
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context "An SQLite dataset" do
|
|
287
|
+
setup do
|
|
288
|
+
SQLITE_DB.create_table! :items do
|
|
289
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
290
|
+
text :name
|
|
291
|
+
float :value
|
|
292
|
+
end
|
|
293
|
+
@d = SQLITE_DB[:items]
|
|
294
|
+
@d.delete # remove all records
|
|
295
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
296
|
+
@d << {:name => 'def', :value => 4.56}
|
|
297
|
+
@d << {:name => 'ghi', :value => 7.89}
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
specify "should correctly return avg" do
|
|
301
|
+
@d.avg(:value).to_s.should == ((1.23 + 4.56 + 7.89) / 3).to_s
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
specify "should correctly return sum" do
|
|
305
|
+
@d.sum(:value).to_s.should == (1.23 + 4.56 + 7.89).to_s
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
specify "should correctly return max" do
|
|
309
|
+
@d.max(:value).to_s.should == 7.89.to_s
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
specify "should correctly return min" do
|
|
313
|
+
@d.min(:value).to_s.should == 1.23.to_s
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
context "SQLite::Dataset#delete" do
|
|
318
|
+
setup do
|
|
319
|
+
SQLITE_DB.create_table! :items do
|
|
320
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
321
|
+
text :name
|
|
322
|
+
float :value
|
|
323
|
+
end
|
|
324
|
+
@d = SQLITE_DB[:items]
|
|
325
|
+
@d.delete # remove all records
|
|
326
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
327
|
+
@d << {:name => 'def', :value => 4.56}
|
|
328
|
+
@d << {:name => 'ghi', :value => 7.89}
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
specify "should return the number of records affected when filtered" do
|
|
332
|
+
@d.count.should == 3
|
|
333
|
+
@d.filter(:value.sql_number < 3).delete.should == 1
|
|
334
|
+
@d.count.should == 2
|
|
335
|
+
|
|
336
|
+
@d.filter(:value.sql_number < 3).delete.should == 0
|
|
337
|
+
@d.count.should == 2
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
specify "should return the number of records affected when unfiltered" do
|
|
341
|
+
@d.count.should == 3
|
|
342
|
+
@d.delete.should == 3
|
|
343
|
+
@d.count.should == 0
|
|
344
|
+
|
|
345
|
+
@d.delete.should == 0
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "SQLite::Dataset#update" do
|
|
350
|
+
setup do
|
|
351
|
+
SQLITE_DB.create_table! :items do
|
|
352
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
353
|
+
text :name
|
|
354
|
+
float :value
|
|
355
|
+
end
|
|
356
|
+
@d = SQLITE_DB[:items]
|
|
357
|
+
@d.delete # remove all records
|
|
358
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
359
|
+
@d << {:name => 'def', :value => 4.56}
|
|
360
|
+
@d << {:name => 'ghi', :value => 7.89}
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
specify "should return the number of records affected" do
|
|
364
|
+
@d.filter(:name => 'abc').update(:value => 2).should == 1
|
|
365
|
+
|
|
366
|
+
@d.update(:value => 10).should == 3
|
|
367
|
+
|
|
368
|
+
@d.filter(:name => 'xxx').update(:value => 23).should == 0
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
context "SQLite dataset" do
|
|
373
|
+
setup do
|
|
374
|
+
SQLITE_DB.create_table! :test do
|
|
375
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
376
|
+
text :name
|
|
377
|
+
float :value
|
|
378
|
+
end
|
|
379
|
+
SQLITE_DB.create_table! :items do
|
|
380
|
+
integer :id, :primary_key => true, :auto_increment => true
|
|
381
|
+
text :name
|
|
382
|
+
float :value
|
|
383
|
+
end
|
|
384
|
+
@d = SQLITE_DB[:items]
|
|
385
|
+
@d.delete # remove all records
|
|
386
|
+
@d << {:name => 'abc', :value => 1.23}
|
|
387
|
+
@d << {:name => 'def', :value => 4.56}
|
|
388
|
+
@d << {:name => 'ghi', :value => 7.89}
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
teardown do
|
|
392
|
+
SQLITE_DB.drop_table :test
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
specify "should be able to insert from a subquery" do
|
|
396
|
+
SQLITE_DB[:test] << @d
|
|
397
|
+
SQLITE_DB[:test].count.should == 3
|
|
398
|
+
SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
|
|
399
|
+
@d.select(:name, :value).order(:value).to_a
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
context "A SQLite database" do
|
|
404
|
+
setup do
|
|
405
|
+
@db = SQLITE_DB
|
|
406
|
+
@db.create_table! :test2 do
|
|
407
|
+
text :name
|
|
408
|
+
integer :value
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
specify "should support add_column operations" do
|
|
413
|
+
@db.add_column :test2, :xyz, :text
|
|
414
|
+
|
|
415
|
+
@db[:test2].columns.should == [:name, :value, :xyz]
|
|
416
|
+
@db[:test2] << {:name => 'mmm', :value => 111, :xyz=>'000'}
|
|
417
|
+
@db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
specify "should support drop_column operations" do
|
|
421
|
+
@db.drop_column :test2, :value
|
|
422
|
+
@db[:test2].columns.should == [:name]
|
|
423
|
+
@db[:test2] << {:name => 'mmm'}
|
|
424
|
+
@db[:test2].first.should == {:name => 'mmm'}
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
specify "should support drop_column operations in a transaction" do
|
|
428
|
+
@db.transaction{@db.drop_column :test2, :value}
|
|
429
|
+
@db[:test2].columns.should == [:name]
|
|
430
|
+
@db[:test2] << {:name => 'mmm'}
|
|
431
|
+
@db[:test2].first.should == {:name => 'mmm'}
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
specify "should keep column attributes when dropping a column" do
|
|
435
|
+
@db.create_table! :test3 do
|
|
436
|
+
primary_key :id
|
|
437
|
+
text :name
|
|
438
|
+
integer :value
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# This lame set of additions and deletions are to test that the primary keys
|
|
442
|
+
# don't get messed up when we recreate the database.
|
|
443
|
+
@db[:test3] << { :name => "foo", :value => 1}
|
|
444
|
+
@db[:test3] << { :name => "foo", :value => 2}
|
|
445
|
+
@db[:test3] << { :name => "foo", :value => 3}
|
|
446
|
+
@db[:test3].filter(:id => 2).delete
|
|
447
|
+
|
|
448
|
+
@db.drop_column :test3, :value
|
|
449
|
+
|
|
450
|
+
@db['PRAGMA table_info(?)', :test3][:id][:pk].to_i.should == 1
|
|
451
|
+
@db[:test3].select(:id).all.should == [{:id => 1}, {:id => 3}]
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
specify "should support rename_column operations" do
|
|
455
|
+
@db[:test2].delete
|
|
456
|
+
@db.add_column :test2, :xyz, :text
|
|
457
|
+
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
|
|
458
|
+
|
|
459
|
+
@db[:test2].columns.should == [:name, :value, :xyz]
|
|
460
|
+
@db.rename_column :test2, :xyz, :zyx, :type => :text
|
|
461
|
+
@db[:test2].columns.should == [:name, :value, :zyx]
|
|
462
|
+
@db[:test2].first[:zyx].should == 'qqqq'
|
|
463
|
+
@db[:test2].count.should eql(1)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
specify "should preserve defaults when dropping or renaming columns" do
|
|
467
|
+
@db.create_table! :test3 do
|
|
468
|
+
String :s, :default=>'a'
|
|
469
|
+
Integer :i
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
@db[:test3].insert
|
|
473
|
+
@db[:test3].first[:s].should == 'a'
|
|
474
|
+
@db[:test3].delete
|
|
475
|
+
@db.drop_column :test3, :i
|
|
476
|
+
@db[:test3].insert
|
|
477
|
+
@db[:test3].first[:s].should == 'a'
|
|
478
|
+
@db[:test3].delete
|
|
479
|
+
@db.rename_column :test3, :s, :t
|
|
480
|
+
@db[:test3].insert
|
|
481
|
+
@db[:test3].first[:t].should == 'a'
|
|
482
|
+
@db[:test3].delete
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
specify "should handle quoted tables when dropping or renaming columns" do
|
|
486
|
+
@db.quote_identifiers = true
|
|
487
|
+
table_name = "T T"
|
|
488
|
+
@db.drop_table(table_name) rescue nil
|
|
489
|
+
@db.create_table! table_name do
|
|
490
|
+
Integer :"s s"
|
|
491
|
+
Integer :"i i"
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
@db.from(table_name).insert(:"s s"=>1, :"i i"=>2)
|
|
495
|
+
@db.from(table_name).all.should == [{:"s s"=>1, :"i i"=>2}]
|
|
496
|
+
@db.drop_column table_name, :"i i"
|
|
497
|
+
@db.from(table_name).all.should == [{:"s s"=>1}]
|
|
498
|
+
@db.rename_column table_name, :"s s", :"t t"
|
|
499
|
+
@db.from(table_name).all.should == [{:"t t"=>1}]
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
specify "should choose a temporary table name that isn't already used when dropping or renaming columns" do
|
|
503
|
+
@db.create_table! :test3 do
|
|
504
|
+
Integer :h
|
|
505
|
+
Integer :i
|
|
506
|
+
end
|
|
507
|
+
@db.create_table! :test3_backup0 do
|
|
508
|
+
Integer :j
|
|
509
|
+
end
|
|
510
|
+
@db.create_table! :test3_backup1 do
|
|
511
|
+
Integer :k
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
@db[:test3].columns.should == [:h, :i]
|
|
515
|
+
@db[:test3_backup0].columns.should == [:j]
|
|
516
|
+
@db[:test3_backup1].columns.should == [:k]
|
|
517
|
+
sqls = @db.drop_column(:test3, :i)
|
|
518
|
+
sqls.any?{|x| x =~ /test3_backup2/}.should == true
|
|
519
|
+
sqls.any?{|x| x =~ /test3_backup[01]/}.should == false
|
|
520
|
+
@db[:test3].columns.should == [:h]
|
|
521
|
+
@db[:test3_backup0].columns.should == [:j]
|
|
522
|
+
@db[:test3_backup1].columns.should == [:k]
|
|
523
|
+
|
|
524
|
+
@db.create_table! :test3_backup2 do
|
|
525
|
+
Integer :l
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
sqls = @db.rename_column(:test3, :h, :i)
|
|
529
|
+
sqls.any?{|x| x =~ /test3_backup3/}.should == true
|
|
530
|
+
sqls.any?{|x| x =~ /test3_backup[012]/}.should == false
|
|
531
|
+
@db[:test3].columns.should == [:i]
|
|
532
|
+
@db[:test3_backup0].columns.should == [:j]
|
|
533
|
+
@db[:test3_backup1].columns.should == [:k]
|
|
534
|
+
@db[:test3_backup2].columns.should == [:l]
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
specify "should not support set_column_type operations" do
|
|
538
|
+
proc {@db.set_column_type :test2, :value, :integer}.should raise_error(Sequel::Error)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
specify "should support add_index" do
|
|
542
|
+
@db.add_index :test2, :value, :unique => true
|
|
543
|
+
@db.add_index :test2, [:name, :value]
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
specify "should support drop_index" do
|
|
547
|
+
@db.add_index :test2, :value, :unique => true
|
|
548
|
+
@db.drop_index :test2, :value
|
|
549
|
+
end
|
|
550
|
+
end
|