sequel_core 1.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 (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