sequel_core 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/CHANGELOG +1003 -0
  2. data/COPYING +18 -0
  3. data/README +81 -0
  4. data/Rakefile +176 -0
  5. data/bin/sequel +41 -0
  6. data/lib/sequel_core.rb +59 -0
  7. data/lib/sequel_core/adapters/adapter_skeleton.rb +68 -0
  8. data/lib/sequel_core/adapters/ado.rb +100 -0
  9. data/lib/sequel_core/adapters/db2.rb +158 -0
  10. data/lib/sequel_core/adapters/dbi.rb +126 -0
  11. data/lib/sequel_core/adapters/informix.rb +87 -0
  12. data/lib/sequel_core/adapters/jdbc.rb +108 -0
  13. data/lib/sequel_core/adapters/mysql.rb +269 -0
  14. data/lib/sequel_core/adapters/odbc.rb +145 -0
  15. data/lib/sequel_core/adapters/odbc_mssql.rb +93 -0
  16. data/lib/sequel_core/adapters/openbase.rb +90 -0
  17. data/lib/sequel_core/adapters/oracle.rb +99 -0
  18. data/lib/sequel_core/adapters/postgres.rb +519 -0
  19. data/lib/sequel_core/adapters/sqlite.rb +192 -0
  20. data/lib/sequel_core/array_keys.rb +296 -0
  21. data/lib/sequel_core/connection_pool.rb +152 -0
  22. data/lib/sequel_core/core_ext.rb +59 -0
  23. data/lib/sequel_core/core_sql.rb +191 -0
  24. data/lib/sequel_core/database.rb +433 -0
  25. data/lib/sequel_core/dataset.rb +409 -0
  26. data/lib/sequel_core/dataset/convenience.rb +321 -0
  27. data/lib/sequel_core/dataset/sequelizer.rb +354 -0
  28. data/lib/sequel_core/dataset/sql.rb +586 -0
  29. data/lib/sequel_core/exceptions.rb +45 -0
  30. data/lib/sequel_core/migration.rb +191 -0
  31. data/lib/sequel_core/model.rb +8 -0
  32. data/lib/sequel_core/pretty_table.rb +73 -0
  33. data/lib/sequel_core/schema.rb +8 -0
  34. data/lib/sequel_core/schema/schema_generator.rb +131 -0
  35. data/lib/sequel_core/schema/schema_sql.rb +131 -0
  36. data/lib/sequel_core/worker.rb +58 -0
  37. data/spec/adapters/informix_spec.rb +139 -0
  38. data/spec/adapters/mysql_spec.rb +330 -0
  39. data/spec/adapters/oracle_spec.rb +130 -0
  40. data/spec/adapters/postgres_spec.rb +189 -0
  41. data/spec/adapters/sqlite_spec.rb +345 -0
  42. data/spec/array_keys_spec.rb +679 -0
  43. data/spec/connection_pool_spec.rb +356 -0
  44. data/spec/core_ext_spec.rb +67 -0
  45. data/spec/core_sql_spec.rb +301 -0
  46. data/spec/database_spec.rb +812 -0
  47. data/spec/dataset_spec.rb +2381 -0
  48. data/spec/migration_spec.rb +261 -0
  49. data/spec/pretty_table_spec.rb +66 -0
  50. data/spec/rcov.opts +4 -0
  51. data/spec/schema_generator_spec.rb +86 -0
  52. data/spec/schema_spec.rb +230 -0
  53. data/spec/sequelizer_spec.rb +448 -0
  54. data/spec/spec.opts +5 -0
  55. data/spec/spec_helper.rb +44 -0
  56. data/spec/worker_spec.rb +96 -0
  57. metadata +162 -0
@@ -0,0 +1,130 @@
1
+ require File.join(File.dirname(__FILE__), '../../lib/sequel')
2
+
3
+ ORACLE_DB = Sequel('oracle://hr:hr@loalhost/XE')
4
+ if ORACLE_DB.table_exists?(:test)
5
+ ORACLE_DB.drop_table :test
6
+ end
7
+ ORACLE_DB.create_table :test do
8
+ text :name
9
+ integer :value
10
+
11
+ index :value
12
+ end
13
+
14
+ context "A Oracle database" do
15
+ specify "should provide disconnect functionality" do
16
+ ORACLE_DB.execute("select user from dual")
17
+ ORACLE_DB.pool.size.should == 1
18
+ ORACLE_DB.disconnect
19
+ ORACLE_DB.pool.size.should == 0
20
+ end
21
+ end
22
+
23
+ context "A Oracle dataset" do
24
+ setup do
25
+ @d = ORACLE_DB[:test]
26
+ @d.delete # remove all records
27
+ end
28
+
29
+ specify "should return the correct record count" do
30
+ @d.count.should == 0
31
+ @d << {:name => 'abc', :value => 123}
32
+ @d << {:name => 'abc', :value => 456}
33
+ @d << {:name => 'def', :value => 789}
34
+ @d.count.should == 3
35
+ end
36
+
37
+ specify "should return the correct records" do
38
+ @d.to_a.should == []
39
+ @d << {:name => 'abc', :value => 123}
40
+ @d << {:name => 'abc', :value => 456}
41
+ @d << {:name => 'def', :value => 789}
42
+
43
+ @d.order(:value).to_a.should == [
44
+ {:name => 'abc', :value => 123},
45
+ {:name => 'abc', :value => 456},
46
+ {:name => 'def', :value => 789}
47
+ ]
48
+ end
49
+
50
+ specify "should update records correctly" do
51
+ @d << {:name => 'abc', :value => 123}
52
+ @d << {:name => 'abc', :value => 456}
53
+ @d << {:name => 'def', :value => 789}
54
+ @d.filter(:name => 'abc').update(:value => 530)
55
+
56
+ # the third record should stay the same
57
+ # floating-point precision bullshit
58
+ @d[:name => 'def'][:value].should == 789
59
+ @d.filter(:value => 530).count.should == 2
60
+ end
61
+
62
+ specify "should delete records correctly" do
63
+ @d << {:name => 'abc', :value => 123}
64
+ @d << {:name => 'abc', :value => 456}
65
+ @d << {:name => 'def', :value => 789}
66
+ @d.filter(:name => 'abc').delete
67
+
68
+ @d.count.should == 1
69
+ @d.first[:name].should == 'def'
70
+ end
71
+
72
+ specify "should be able to literalize booleans" do
73
+ proc {@d.literal(true)}.should_not raise_error
74
+ proc {@d.literal(false)}.should_not raise_error
75
+ end
76
+
77
+ specify "should support transactions" do
78
+ ORACLE_DB.transaction do
79
+ @d << {:name => 'abc', :value => 1}
80
+ end
81
+
82
+ @d.count.should == 1
83
+ end
84
+ end
85
+
86
+ context "A Oracle dataset in array tuples mode" do
87
+ setup do
88
+ @d = ORACLE_DB[:test]
89
+ @d.delete # remove all records
90
+ Sequel.use_array_tuples
91
+ end
92
+
93
+ teardown do
94
+ Sequel.use_hash_tuples
95
+ end
96
+
97
+ specify "should return the correct records" do
98
+ @d.to_a.should == []
99
+ @d << {:name => 'abc', :value => 123}
100
+ @d << {:name => 'abc', :value => 456}
101
+ @d << {:name => 'def', :value => 789}
102
+
103
+ @d.order(:value).select(:name, :value).to_a.should == [
104
+ ['abc', 123],
105
+ ['abc', 456],
106
+ ['def', 789]
107
+ ]
108
+ end
109
+
110
+ specify "should work correctly with transforms" do
111
+ @d.transform(:value => [proc {|v| v.to_s}, proc {|v| v.to_i}])
112
+
113
+ @d.to_a.should == []
114
+ @d << {:name => 'abc', :value => 123}
115
+ @d << {:name => 'abc', :value => 456}
116
+ @d << {:name => 'def', :value => 789}
117
+
118
+ @d.order(:value).select(:name, :value).to_a.should == [
119
+ ['abc', '123'],
120
+ ['abc', '456'],
121
+ ['def', '789']
122
+ ]
123
+
124
+ a = @d.order(:value).first
125
+ a.values.should == ['abc', '123']
126
+ a.keys.should == [:name, :value]
127
+ a[:name].should == 'abc'
128
+ a[:value].should == '123'
129
+ end
130
+ end
@@ -0,0 +1,189 @@
1
+ require File.join(File.dirname(__FILE__), '../../lib/sequel')
2
+
3
+ PGSQL_DB = Sequel('postgres://postgres:postgres@localhost:5432/reality_spec')
4
+ PGSQL_DB.drop_table(:test) if PGSQL_DB.table_exists?(:test)
5
+ PGSQL_DB.drop_table(:test2) if PGSQL_DB.table_exists?(:test2)
6
+
7
+ PGSQL_DB.create_table :test do
8
+ text :name
9
+ integer :value, :index => true
10
+ end
11
+ PGSQL_DB.create_table :test2 do
12
+ text :name
13
+ integer :value
14
+ end
15
+
16
+ context "A PostgreSQL database" do
17
+ setup do
18
+ @db = PGSQL_DB
19
+ end
20
+
21
+ specify "should provide disconnect functionality" do
22
+ @db.tables
23
+ @db.pool.size.should == 1
24
+ @db.disconnect
25
+ @db.pool.size.should == 0
26
+ end
27
+ end
28
+
29
+ context "A PostgreSQL dataset" do
30
+ setup do
31
+ @d = PGSQL_DB[:test]
32
+ @d.delete # remove all records
33
+ end
34
+
35
+ specify "should return the correct record count" do
36
+ @d.count.should == 0
37
+ @d << {:name => 'abc', :value => 123}
38
+ @d << {:name => 'abc', :value => 456}
39
+ @d << {:name => 'def', :value => 789}
40
+ @d.count.should == 3
41
+ end
42
+
43
+ specify "should return the correct records" do
44
+ @d.to_a.should == []
45
+ @d << {:name => 'abc', :value => 123}
46
+ @d << {:name => 'abc', :value => 456}
47
+ @d << {:name => 'def', :value => 789}
48
+
49
+ @d.order(:value).to_a.should == [
50
+ {:name => 'abc', :value => 123},
51
+ {:name => 'abc', :value => 456},
52
+ {:name => 'def', :value => 789}
53
+ ]
54
+ end
55
+
56
+ specify "should update records correctly" do
57
+ @d << {:name => 'abc', :value => 123}
58
+ @d << {:name => 'abc', :value => 456}
59
+ @d << {:name => 'def', :value => 789}
60
+ @d.filter(:name => 'abc').update(:value => 530)
61
+
62
+ # the third record should stay the same
63
+ # floating-point precision bullshit
64
+ @d[:name => 'def'][:value].should == 789
65
+ @d.filter(:value => 530).count.should == 2
66
+ end
67
+
68
+ specify "should delete records correctly" do
69
+ @d << {:name => 'abc', :value => 123}
70
+ @d << {:name => 'abc', :value => 456}
71
+ @d << {:name => 'def', :value => 789}
72
+ @d.filter(:name => 'abc').delete
73
+
74
+ @d.count.should == 1
75
+ @d.first[:name].should == 'def'
76
+ end
77
+
78
+ specify "should be able to literalize booleans" do
79
+ proc {@d.literal(true)}.should_not raise_error
80
+ proc {@d.literal(false)}.should_not raise_error
81
+ end
82
+
83
+ specify "should support transactions" do
84
+ PGSQL_DB.transaction do
85
+ @d << {:name => 'abc', :value => 1}
86
+ end
87
+
88
+ @d.count.should == 1
89
+ end
90
+
91
+ specify "should support regexps" do
92
+ @d << {:name => 'abc', :value => 1}
93
+ @d << {:name => 'bcd', :value => 2}
94
+ @d.filter(:name => /bc/).count.should == 2
95
+ @d.filter(:name => /^bc/).count.should == 1
96
+ end
97
+
98
+ specify "should consider strings containing backslashes to be escaped string literals" do
99
+ PGconn.quote("\\dingo").should == "E'\\\\dingo'" # literally, E'\\dingo'
100
+ PGconn.quote("dingo").should == "'dingo'"
101
+ end
102
+ end
103
+
104
+ context "A PostgreSQL dataset in array tuples mode" do
105
+ setup do
106
+ @d = PGSQL_DB[:test]
107
+ @d.delete # remove all records
108
+ Sequel.use_array_tuples
109
+ end
110
+
111
+ teardown do
112
+ Sequel.use_hash_tuples
113
+ end
114
+
115
+ specify "should return the correct records" do
116
+ @d.to_a.should == []
117
+ @d << {:name => 'abc', :value => 123}
118
+ @d << {:name => 'abc', :value => 456}
119
+ @d << {:name => 'def', :value => 789}
120
+
121
+ @d.order(:value).select(:name, :value).to_a.should == [
122
+ ['abc', 123],
123
+ ['abc', 456],
124
+ ['def', 789]
125
+ ]
126
+ end
127
+
128
+ specify "should work correctly with transforms" do
129
+ @d.transform(:value => [proc {|v| v.to_s}, proc {|v| v.to_i}])
130
+
131
+ @d.to_a.should == []
132
+ @d << {:name => 'abc', :value => 123}
133
+ @d << {:name => 'abc', :value => 456}
134
+ @d << {:name => 'def', :value => 789}
135
+
136
+ @d.order(:value).select(:name, :value).to_a.should == [
137
+ ['abc', '123'],
138
+ ['abc', '456'],
139
+ ['def', '789']
140
+ ]
141
+
142
+ a = @d.order(:value).first
143
+ a.values.should == ['abc', '123']
144
+ a.keys.should == [:name, :value]
145
+ a[:name].should == 'abc'
146
+ a[:value].should == '123'
147
+ end
148
+ end
149
+
150
+ context "A PostgreSQL database" do
151
+ setup do
152
+ @db = PGSQL_DB
153
+ end
154
+
155
+ specify "should support add_column operations" do
156
+ @db.add_column :test2, :xyz, :text, :default => '000'
157
+
158
+ @db[:test2].columns.should == [:name, :value, :xyz]
159
+ @db[:test2] << {:name => 'mmm', :value => 111}
160
+ @db[:test2].first[:xyz].should == '000'
161
+ end
162
+
163
+ specify "should support drop_column operations" do
164
+ @db[:test2].columns.should == [:name, :value, :xyz]
165
+ @db.drop_column :test2, :xyz
166
+
167
+ @db[:test2].columns.should == [:name, :value]
168
+ end
169
+
170
+ specify "should support rename_column operations" do
171
+ @db[:test2].delete
172
+ @db.add_column :test2, :xyz, :text, :default => '000'
173
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
174
+
175
+ @db[:test2].columns.should == [:name, :value, :xyz]
176
+ @db.rename_column :test2, :xyz, :zyx
177
+ @db[:test2].columns.should == [:name, :value, :zyx]
178
+ @db[:test2].first[:zyx].should == 'qqqq'
179
+ end
180
+
181
+ specify "should support set_column_type operations" do
182
+ @db.add_column :test2, :xyz, :float
183
+ @db[:test2].delete
184
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 56.78}
185
+ @db.set_column_type :test2, :xyz, :integer
186
+
187
+ @db[:test2].first[:xyz].should == 57
188
+ end
189
+ end
@@ -0,0 +1,345 @@
1
+ require File.join(File.dirname(__FILE__), '../../lib/sequel')
2
+
3
+ SQLITE_DB = Sequel('sqlite:/')
4
+ SQLITE_DB.create_table :items do
5
+ integer :id, :primary_key => true, :auto_increment => true
6
+ text :name
7
+ float :value
8
+ end
9
+ SQLITE_DB.create_table :test2 do
10
+ text :name
11
+ integer :value
12
+ end
13
+ SQLITE_DB.create_table(:time) {timestamp :t}
14
+
15
+ context "An SQLite database" do
16
+ setup do
17
+ @db = Sequel('sqlite:/')
18
+ end
19
+
20
+ specify "should provide a list of existing tables" do
21
+ @db.tables.should == []
22
+
23
+ @db.create_table :testing do
24
+ text :name
25
+ end
26
+ @db.tables.should include(:testing)
27
+ end
28
+
29
+ specify "should support getting pragma values" do
30
+ @db.pragma_get(:auto_vacuum).should == '0'
31
+ end
32
+
33
+ specify "should support setting pragma values" do
34
+ @db.pragma_set(:auto_vacuum, '1')
35
+ @db.pragma_get(:auto_vacuum).should == '1'
36
+ end
37
+
38
+ specify "should support getting and setting the auto_vacuum pragma" do
39
+ @db.auto_vacuum = :full
40
+ @db.auto_vacuum.should == :full
41
+ @db.auto_vacuum = :none
42
+ @db.auto_vacuum.should == :none
43
+
44
+ proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
45
+ end
46
+
47
+ specify "should support getting and setting the synchronous pragma" do
48
+ @db.synchronous = :off
49
+ @db.synchronous.should == :off
50
+ @db.synchronous = :normal
51
+ @db.synchronous.should == :normal
52
+ @db.synchronous = :full
53
+ @db.synchronous.should == :full
54
+
55
+ proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
56
+ end
57
+
58
+ specify "should support getting and setting the temp_store pragma" do
59
+ @db.temp_store = :default
60
+ @db.temp_store.should == :default
61
+ @db.temp_store = :file
62
+ @db.temp_store.should == :file
63
+ @db.temp_store = :memory
64
+ @db.temp_store.should == :memory
65
+
66
+ proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
67
+ end
68
+
69
+ specify "should be able to execute multiple statements at once" do
70
+ @db.create_table :t do
71
+ text :name
72
+ end
73
+
74
+ @db << "insert into t (name) values ('abc');insert into t (name) values ('def')"
75
+
76
+ @db[:t].count.should == 2
77
+
78
+ @db[:t].order(:name).map(:name).should == ['abc', 'def']
79
+ end
80
+
81
+ specify "should be able to execute transactions" do
82
+ @db.transaction do
83
+ @db.create_table(:t) {text :name}
84
+ end
85
+
86
+ @db.tables.should == [:t]
87
+
88
+ proc {@db.transaction do
89
+ @db.create_table(:u) {text :name}
90
+ raise ArgumentError
91
+ end}.should raise_error(ArgumentError)
92
+ # no commit
93
+ @db.tables.should == [:t]
94
+
95
+ proc {@db.transaction do
96
+ @db.create_table(:v) {text :name}
97
+ rollback!
98
+ end}.should_not raise_error
99
+ # no commit
100
+ @db.tables.should == [:t]
101
+ end
102
+
103
+ specify "should support nested transactions" do
104
+ @db.transaction do
105
+ @db.transaction do
106
+ @db.create_table(:t) {text :name}
107
+ end
108
+ end
109
+
110
+ @db.tables.should == [:t]
111
+
112
+ proc {@db.transaction do
113
+ @db.create_table(:v) {text :name}
114
+ @db.transaction do
115
+ rollback! # should roll back the top-level transaction
116
+ end
117
+ end}.should_not raise_error
118
+ # no commit
119
+ @db.tables.should == [:t]
120
+ end
121
+
122
+ specify "should provide disconnect functionality" do
123
+ @db.tables
124
+ @db.pool.size.should == 1
125
+ @db.disconnect
126
+ @db.pool.size.should == 0
127
+ end
128
+
129
+ specify "should support timestamps" do
130
+ t1 = Time.at(Time.now.to_i) #normalize time
131
+
132
+ SQLITE_DB[:time] << {:t => t1}
133
+ SQLITE_DB[:time].first[:t].should == t1
134
+ end
135
+ end
136
+
137
+ context "An SQLite dataset" do
138
+ setup do
139
+ @d = SQLITE_DB[:items]
140
+ @d.delete # remove all records
141
+ end
142
+
143
+ specify "should return the correct records" do
144
+ @d.to_a.should == []
145
+ @d << {:name => 'abc', :value => 1.23}
146
+ @d << {:name => 'abc', :value => 4.56}
147
+ @d << {:name => 'def', :value => 7.89}
148
+ @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
149
+ {:name => 'abc', :value => 1.23},
150
+ {:name => 'abc', :value => 4.56},
151
+ {:name => 'def', :value => 7.89}
152
+ ]
153
+ end
154
+
155
+ specify "should return the correct record count" do
156
+ @d.count.should == 0
157
+ @d << {:name => 'abc', :value => 1.23}
158
+ @d << {:name => 'abc', :value => 4.56}
159
+ @d << {:name => 'def', :value => 7.89}
160
+ @d.count.should == 3
161
+ end
162
+
163
+ specify "should return the last inserted id when inserting records" do
164
+ id = @d << {:name => 'abc', :value => 1.23}
165
+ id.should == @d.first[:id]
166
+ end
167
+
168
+ specify "should update records correctly" do
169
+ @d << {:name => 'abc', :value => 1.23}
170
+ @d << {:name => 'abc', :value => 4.56}
171
+ @d << {:name => 'def', :value => 7.89}
172
+ @d.filter(:name => 'abc').update(:value => 5.3)
173
+
174
+ # the third record should stay the same
175
+ @d[:name => 'def'][:value].should == 7.89
176
+ @d.filter(:value => 5.3).count.should == 2
177
+ end
178
+
179
+ specify "should delete records correctly" do
180
+ @d << {:name => 'abc', :value => 1.23}
181
+ @d << {:name => 'abc', :value => 4.56}
182
+ @d << {:name => 'def', :value => 7.89}
183
+ @d.filter(:name => 'abc').delete
184
+
185
+ @d.count.should == 1
186
+ @d.first[:name].should == 'def'
187
+ end
188
+ end
189
+
190
+ context "An SQLite dataset" do
191
+ setup do
192
+ @d = SQLITE_DB[:items]
193
+ @d.delete # remove all records
194
+ @d << {:name => 'abc', :value => 1.23}
195
+ @d << {:name => 'def', :value => 4.56}
196
+ @d << {:name => 'ghi', :value => 7.89}
197
+ end
198
+
199
+ specify "should correctly return avg" do
200
+ @d.avg(:value).should == ((1.23 + 4.56 + 7.89) / 3).to_s
201
+ end
202
+
203
+ specify "should correctly return sum" do
204
+ @d.sum(:value).should == (1.23 + 4.56 + 7.89).to_s
205
+ end
206
+
207
+ specify "should correctly return max" do
208
+ @d.max(:value).should == 7.89.to_s
209
+ end
210
+
211
+ specify "should correctly return min" do
212
+ @d.min(:value).should == 1.23.to_s
213
+ end
214
+ end
215
+
216
+ context "SQLite::Dataset#delete" do
217
+ setup do
218
+ @d = SQLITE_DB[:items]
219
+ @d.delete # remove all records
220
+ @d << {:name => 'abc', :value => 1.23}
221
+ @d << {:name => 'def', :value => 4.56}
222
+ @d << {:name => 'ghi', :value => 7.89}
223
+ end
224
+
225
+ specify "should return the number of records affected when filtered" do
226
+ @d.count.should == 3
227
+ @d.filter {:value < 3}.delete.should == 1
228
+ @d.count.should == 2
229
+
230
+ @d.filter {:value < 3}.delete.should == 0
231
+ @d.count.should == 2
232
+ end
233
+
234
+ specify "should return the number of records affected when unfiltered" do
235
+ @d.count.should == 3
236
+ @d.delete.should == 3
237
+ @d.count.should == 0
238
+
239
+ @d.delete.should == 0
240
+ end
241
+ end
242
+
243
+ context "SQLite::Dataset#update" do
244
+ setup do
245
+ @d = SQLITE_DB[:items]
246
+ @d.delete # remove all records
247
+ @d << {:name => 'abc', :value => 1.23}
248
+ @d << {:name => 'def', :value => 4.56}
249
+ @d << {:name => 'ghi', :value => 7.89}
250
+ end
251
+
252
+ specify "should return the number of records affected" do
253
+ @d.filter(:name => 'abc').update(:value => 2).should == 1
254
+
255
+ @d.update(:value => 10).should == 3
256
+
257
+ @d.filter(:name => 'xxx').update(:value => 23).should == 0
258
+ end
259
+ end
260
+
261
+ context "An SQLite dataset in array tuples mode" do
262
+ setup do
263
+ @d = SQLITE_DB[:items]
264
+ @d.delete # remove all records
265
+
266
+ Sequel.use_array_tuples
267
+ end
268
+
269
+ teardown do
270
+ Sequel.use_hash_tuples
271
+ end
272
+
273
+ specify "should return the correct records" do
274
+ @d.to_a.should == []
275
+ @d << {:name => 'abc', :value => 1.23}
276
+ @d << {:name => 'abc', :value => 4.56}
277
+ @d << {:name => 'def', :value => 7.89}
278
+ @d.select(:name, :value).to_a.sort_by {|h| h[:value]}.should == [
279
+ ['abc', 1.23],
280
+ ['abc', 4.56],
281
+ ['def', 7.89]
282
+ ]
283
+ end
284
+ end
285
+
286
+ context "SQLite dataset" do
287
+ setup do
288
+ SQLITE_DB.create_table :test do
289
+ integer :id, :primary_key => true, :auto_increment => true
290
+ text :name
291
+ float :value
292
+ end
293
+
294
+ @d = SQLITE_DB[:items]
295
+ @d.delete # remove all records
296
+ @d << {:name => 'abc', :value => 1.23}
297
+ @d << {:name => 'def', :value => 4.56}
298
+ @d << {:name => 'ghi', :value => 7.89}
299
+ end
300
+
301
+ teardown do
302
+ SQLITE_DB.drop_table :test
303
+ end
304
+
305
+ specify "should be able to insert from a subquery" do
306
+ SQLITE_DB[:test] << @d
307
+ SQLITE_DB[:test].count.should == 3
308
+ SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
309
+ @d.select(:name, :value).order(:value).to_a
310
+ end
311
+ end
312
+
313
+ context "A SQLite database" do
314
+ setup do
315
+ @db = SQLITE_DB
316
+ end
317
+
318
+ specify "should support add_column operations" do
319
+ @db.add_column :test2, :xyz, :text
320
+
321
+ @db[:test2].columns.should == [:name, :value, :xyz]
322
+ @db[:test2] << {:name => 'mmm', :value => 111}
323
+ @db[:test2].first[:xyz].should == '000'
324
+ end
325
+
326
+ specify "should not support drop_column operations" do
327
+ proc {@db.drop_column :test2, :xyz}.should raise_error(SequelError)
328
+ end
329
+
330
+ specify "should not support rename_column operations" do
331
+ @db[:test2].delete
332
+ @db.add_column :test2, :xyz, :text, :default => '000'
333
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
334
+
335
+ @db[:test2].columns.should == [:name, :value, :xyz]
336
+ proc {@db.rename_column :test2, :xyz, :zyx}.should raise_error(SequelError)
337
+ end
338
+
339
+ specify "should not support set_column_type operations" do
340
+ @db.add_column :test2, :xyz, :float
341
+ @db[:test2].delete
342
+ @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 56.78}
343
+ proc {@db.set_column_type :test2, :xyz, :integer}.should raise_error(SequelError)
344
+ end
345
+ end