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.
Files changed (134) hide show
  1. data/README.rdoc +652 -0
  2. data/VERSION.yml +4 -0
  3. data/bin/sequel +104 -0
  4. data/lib/sequel.rb +1 -0
  5. data/lib/sequel/adapters/ado.rb +85 -0
  6. data/lib/sequel/adapters/db2.rb +132 -0
  7. data/lib/sequel/adapters/dbi.rb +101 -0
  8. data/lib/sequel/adapters/do.rb +197 -0
  9. data/lib/sequel/adapters/do/mysql.rb +38 -0
  10. data/lib/sequel/adapters/do/postgres.rb +92 -0
  11. data/lib/sequel/adapters/do/sqlite.rb +31 -0
  12. data/lib/sequel/adapters/firebird.rb +307 -0
  13. data/lib/sequel/adapters/informix.rb +75 -0
  14. data/lib/sequel/adapters/jdbc.rb +485 -0
  15. data/lib/sequel/adapters/jdbc/h2.rb +62 -0
  16. data/lib/sequel/adapters/jdbc/mysql.rb +56 -0
  17. data/lib/sequel/adapters/jdbc/oracle.rb +23 -0
  18. data/lib/sequel/adapters/jdbc/postgresql.rb +101 -0
  19. data/lib/sequel/adapters/jdbc/sqlite.rb +43 -0
  20. data/lib/sequel/adapters/mysql.rb +370 -0
  21. data/lib/sequel/adapters/odbc.rb +184 -0
  22. data/lib/sequel/adapters/openbase.rb +57 -0
  23. data/lib/sequel/adapters/oracle.rb +140 -0
  24. data/lib/sequel/adapters/postgres.rb +453 -0
  25. data/lib/sequel/adapters/shared/mssql.rb +93 -0
  26. data/lib/sequel/adapters/shared/mysql.rb +341 -0
  27. data/lib/sequel/adapters/shared/oracle.rb +62 -0
  28. data/lib/sequel/adapters/shared/postgres.rb +743 -0
  29. data/lib/sequel/adapters/shared/progress.rb +34 -0
  30. data/lib/sequel/adapters/shared/sqlite.rb +263 -0
  31. data/lib/sequel/adapters/sqlite.rb +243 -0
  32. data/lib/sequel/adapters/utils/date_format.rb +21 -0
  33. data/lib/sequel/adapters/utils/stored_procedures.rb +75 -0
  34. data/lib/sequel/adapters/utils/unsupported.rb +62 -0
  35. data/lib/sequel/connection_pool.rb +258 -0
  36. data/lib/sequel/core.rb +204 -0
  37. data/lib/sequel/core_sql.rb +185 -0
  38. data/lib/sequel/database.rb +687 -0
  39. data/lib/sequel/database/schema_generator.rb +324 -0
  40. data/lib/sequel/database/schema_methods.rb +164 -0
  41. data/lib/sequel/database/schema_sql.rb +324 -0
  42. data/lib/sequel/dataset.rb +422 -0
  43. data/lib/sequel/dataset/convenience.rb +237 -0
  44. data/lib/sequel/dataset/prepared_statements.rb +220 -0
  45. data/lib/sequel/dataset/sql.rb +1105 -0
  46. data/lib/sequel/deprecated.rb +529 -0
  47. data/lib/sequel/exceptions.rb +44 -0
  48. data/lib/sequel/extensions/blank.rb +42 -0
  49. data/lib/sequel/extensions/inflector.rb +288 -0
  50. data/lib/sequel/extensions/pagination.rb +96 -0
  51. data/lib/sequel/extensions/pretty_table.rb +78 -0
  52. data/lib/sequel/extensions/query.rb +48 -0
  53. data/lib/sequel/extensions/string_date_time.rb +47 -0
  54. data/lib/sequel/metaprogramming.rb +44 -0
  55. data/lib/sequel/migration.rb +212 -0
  56. data/lib/sequel/model.rb +142 -0
  57. data/lib/sequel/model/association_reflection.rb +263 -0
  58. data/lib/sequel/model/associations.rb +1024 -0
  59. data/lib/sequel/model/base.rb +911 -0
  60. data/lib/sequel/model/deprecated.rb +188 -0
  61. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  62. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  63. data/lib/sequel/model/deprecated_validations.rb +384 -0
  64. data/lib/sequel/model/errors.rb +37 -0
  65. data/lib/sequel/model/exceptions.rb +7 -0
  66. data/lib/sequel/model/inflections.rb +230 -0
  67. data/lib/sequel/model/plugins.rb +74 -0
  68. data/lib/sequel/object_graph.rb +230 -0
  69. data/lib/sequel/plugins/caching.rb +122 -0
  70. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  71. data/lib/sequel/plugins/schema.rb +53 -0
  72. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  73. data/lib/sequel/plugins/validation_class_methods.rb +373 -0
  74. data/lib/sequel/sql.rb +854 -0
  75. data/lib/sequel/version.rb +11 -0
  76. data/lib/sequel_core.rb +1 -0
  77. data/lib/sequel_model.rb +1 -0
  78. data/spec/adapters/ado_spec.rb +46 -0
  79. data/spec/adapters/firebird_spec.rb +376 -0
  80. data/spec/adapters/informix_spec.rb +96 -0
  81. data/spec/adapters/mysql_spec.rb +875 -0
  82. data/spec/adapters/oracle_spec.rb +272 -0
  83. data/spec/adapters/postgres_spec.rb +692 -0
  84. data/spec/adapters/spec_helper.rb +10 -0
  85. data/spec/adapters/sqlite_spec.rb +550 -0
  86. data/spec/core/connection_pool_spec.rb +526 -0
  87. data/spec/core/core_ext_spec.rb +156 -0
  88. data/spec/core/core_sql_spec.rb +528 -0
  89. data/spec/core/database_spec.rb +1214 -0
  90. data/spec/core/dataset_spec.rb +3513 -0
  91. data/spec/core/expression_filters_spec.rb +363 -0
  92. data/spec/core/migration_spec.rb +261 -0
  93. data/spec/core/object_graph_spec.rb +280 -0
  94. data/spec/core/pretty_table_spec.rb +58 -0
  95. data/spec/core/schema_generator_spec.rb +167 -0
  96. data/spec/core/schema_spec.rb +778 -0
  97. data/spec/core/spec_helper.rb +82 -0
  98. data/spec/core/version_spec.rb +7 -0
  99. data/spec/extensions/blank_spec.rb +67 -0
  100. data/spec/extensions/caching_spec.rb +201 -0
  101. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  102. data/spec/extensions/inflector_spec.rb +122 -0
  103. data/spec/extensions/pagination_spec.rb +99 -0
  104. data/spec/extensions/pretty_table_spec.rb +91 -0
  105. data/spec/extensions/query_spec.rb +85 -0
  106. data/spec/extensions/schema_spec.rb +111 -0
  107. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  108. data/spec/extensions/spec_helper.rb +90 -0
  109. data/spec/extensions/string_date_time_spec.rb +93 -0
  110. data/spec/extensions/validation_class_methods_spec.rb +1054 -0
  111. data/spec/integration/dataset_test.rb +160 -0
  112. data/spec/integration/eager_loader_test.rb +683 -0
  113. data/spec/integration/prepared_statement_test.rb +130 -0
  114. data/spec/integration/schema_test.rb +183 -0
  115. data/spec/integration/spec_helper.rb +75 -0
  116. data/spec/integration/type_test.rb +96 -0
  117. data/spec/model/association_reflection_spec.rb +93 -0
  118. data/spec/model/associations_spec.rb +1780 -0
  119. data/spec/model/base_spec.rb +494 -0
  120. data/spec/model/caching_spec.rb +217 -0
  121. data/spec/model/dataset_methods_spec.rb +78 -0
  122. data/spec/model/eager_loading_spec.rb +1165 -0
  123. data/spec/model/hooks_spec.rb +472 -0
  124. data/spec/model/inflector_spec.rb +126 -0
  125. data/spec/model/model_spec.rb +588 -0
  126. data/spec/model/plugins_spec.rb +142 -0
  127. data/spec/model/record_spec.rb +1243 -0
  128. data/spec/model/schema_spec.rb +92 -0
  129. data/spec/model/spec_helper.rb +124 -0
  130. data/spec/model/validations_spec.rb +1080 -0
  131. data/spec/rcov.opts +6 -0
  132. data/spec/spec.opts +0 -0
  133. data/spec/spec_config.rb.example +10 -0
  134. 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